更新libclamav库1.0.0版本
This commit is contained in:
7
clamav/libclamav_rust/.cargo/config.toml
Normal file
7
clamav/libclamav_rust/.cargo/config.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
[source.crates-io]
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source.vendored-sources]
|
||||
directory = ".cargo/vendor"
|
||||
|
||||
1
clamav/libclamav_rust/.cargo/vendor/adler/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/adler/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"CHANGELOG.md":"737088e45fdf27fe2cfedce163332d8ce08c58fd86ca287de2de34c0fbaf63e7","Cargo.toml":"f410869f0f1a5697f65a8a77be03da7aeecc0be26e7cf3a1feb1acaa4f518770","LICENSE-0BSD":"861399f8c21c042b110517e76dc6b63a2b334276c8cf17412fc3c8908ca8dc17","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"308c50cdb42b9573743068158339570b45ca3f895015ca3b87ba983edb0a21e6","RELEASE_PROCESS.md":"a86cd10fc70f167f8d00e9e4ce0c6b4ebdfa1865058390dffd1e0ad4d3e68d9d","benches/bench.rs":"c07ce370e3680c602e415f8d1ec4e543ea2163ab22a09b6b82d93e8a30adca82","src/algo.rs":"b664b131f724a809591394a10b9023f40ab5963e32a83fa3163c2668e59c8b66","src/lib.rs":"b55ba9c629b30360d08168b2ca0c96275432856a539737a105a6d6ae6bf7e88f"},"package":"f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"}
|
||||
63
clamav/libclamav_rust/.cargo/vendor/adler/CHANGELOG.md
vendored
Normal file
63
clamav/libclamav_rust/.cargo/vendor/adler/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
No changes.
|
||||
|
||||
## [1.0.2 - 2021-02-26](https://github.com/jonas-schievink/adler/releases/tag/v1.0.2)
|
||||
|
||||
- Fix doctest on big-endian systems ([#9]).
|
||||
|
||||
[#9]: https://github.com/jonas-schievink/adler/pull/9
|
||||
|
||||
## [1.0.1 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.1)
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix documentation on docs.rs.
|
||||
|
||||
## [1.0.0 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.0)
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix `cargo test --no-default-features` ([#5]).
|
||||
|
||||
### Improvements
|
||||
|
||||
- Extended and clarified documentation.
|
||||
- Added more rustdoc examples.
|
||||
- Extended CI to test the crate with `--no-default-features`.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- `adler32_reader` now takes its generic argument by value instead of as a `&mut`.
|
||||
- Renamed `adler32_reader` to `adler32`.
|
||||
|
||||
## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3)
|
||||
|
||||
- Process 4 Bytes at a time, improving performance by up to 50% ([#2]).
|
||||
|
||||
## [0.2.2 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.2)
|
||||
|
||||
- Bump MSRV to 1.31.0.
|
||||
|
||||
## [0.2.1 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.1)
|
||||
|
||||
- Add a few `#[inline]` annotations to small functions.
|
||||
- Fix CI badge.
|
||||
- Allow integration into libstd.
|
||||
|
||||
## [0.2.0 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.0)
|
||||
|
||||
- Support `#![no_std]` when using `default-features = false`.
|
||||
- Improve performance by around 7x.
|
||||
- Support Rust 1.8.0.
|
||||
- Improve API naming.
|
||||
|
||||
## [0.1.0 - 2020-06-26](https://github.com/jonas-schievink/adler/releases/tag/v0.1.0)
|
||||
|
||||
Initial release.
|
||||
|
||||
|
||||
[#2]: https://github.com/jonas-schievink/adler/pull/2
|
||||
[#5]: https://github.com/jonas-schievink/adler/pull/5
|
||||
64
clamav/libclamav_rust/.cargo/vendor/adler/Cargo.toml
vendored
Normal file
64
clamav/libclamav_rust/.cargo/vendor/adler/Cargo.toml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
# 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 = "adler"
|
||||
version = "1.0.2"
|
||||
authors = ["Jonas Schievink <jonasschievink@gmail.com>"]
|
||||
description = "A simple clean-room implementation of the Adler-32 checksum"
|
||||
documentation = "https://docs.rs/adler/"
|
||||
readme = "README.md"
|
||||
keywords = ["checksum", "integrity", "hash", "adler32", "zlib"]
|
||||
categories = ["algorithms"]
|
||||
license = "0BSD OR MIT OR Apache-2.0"
|
||||
repository = "https://github.com/jonas-schievink/adler.git"
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--cfg=docsrs"]
|
||||
|
||||
[package.metadata.release]
|
||||
no-dev-version = true
|
||||
pre-release-commit-message = "Release {{version}}"
|
||||
tag-message = "{{version}}"
|
||||
|
||||
[[package.metadata.release.pre-release-replacements]]
|
||||
file = "CHANGELOG.md"
|
||||
replace = "## Unreleased\n\nNo changes.\n\n## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}})\n"
|
||||
search = "## Unreleased\n"
|
||||
|
||||
[[package.metadata.release.pre-release-replacements]]
|
||||
file = "README.md"
|
||||
replace = "adler = \"{{version}}\""
|
||||
search = "adler = \"[a-z0-9\\\\.-]+\""
|
||||
|
||||
[[package.metadata.release.pre-release-replacements]]
|
||||
file = "src/lib.rs"
|
||||
replace = "https://docs.rs/adler/{{version}}"
|
||||
search = "https://docs.rs/adler/[a-z0-9\\.-]+"
|
||||
|
||||
[[bench]]
|
||||
name = "bench"
|
||||
harness = false
|
||||
[dependencies.compiler_builtins]
|
||||
version = "0.1.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.core]
|
||||
version = "1.0.0"
|
||||
optional = true
|
||||
package = "rustc-std-workspace-core"
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.3.2"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
rustc-dep-of-std = ["core", "compiler_builtins"]
|
||||
std = []
|
||||
12
clamav/libclamav_rust/.cargo/vendor/adler/LICENSE-0BSD
vendored
Normal file
12
clamav/libclamav_rust/.cargo/vendor/adler/LICENSE-0BSD
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Copyright (C) Jonas Schievink <jonasschievink@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for
|
||||
any purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
201
clamav/libclamav_rust/.cargo/vendor/adler/LICENSE-APACHE
vendored
Normal file
201
clamav/libclamav_rust/.cargo/vendor/adler/LICENSE-APACHE
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
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
|
||||
|
||||
https://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.
|
||||
23
clamav/libclamav_rust/.cargo/vendor/adler/LICENSE-MIT
vendored
Normal file
23
clamav/libclamav_rust/.cargo/vendor/adler/LICENSE-MIT
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
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.
|
||||
39
clamav/libclamav_rust/.cargo/vendor/adler/README.md
vendored
Normal file
39
clamav/libclamav_rust/.cargo/vendor/adler/README.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
# Adler-32 checksums for Rust
|
||||
|
||||
[](https://crates.io/crates/adler)
|
||||
[](https://docs.rs/adler/)
|
||||

|
||||
|
||||
This crate provides a simple implementation of the Adler-32 checksum, used in
|
||||
the zlib compression format.
|
||||
|
||||
Please refer to the [changelog](CHANGELOG.md) to see what changed in the last
|
||||
releases.
|
||||
|
||||
## Features
|
||||
|
||||
- Permissively licensed (0BSD) clean-room implementation.
|
||||
- Zero dependencies.
|
||||
- Zero `unsafe`.
|
||||
- Decent performance (3-4 GB/s).
|
||||
- Supports `#![no_std]` (with `default-features = false`).
|
||||
|
||||
## Usage
|
||||
|
||||
Add an entry to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
adler = "1.0.2"
|
||||
```
|
||||
|
||||
Check the [API Documentation](https://docs.rs/adler/) for how to use the
|
||||
crate's functionality.
|
||||
|
||||
## Rust version support
|
||||
|
||||
Currently, this crate supports all Rust versions starting at Rust 1.31.0.
|
||||
|
||||
Bumping the Minimum Supported Rust Version (MSRV) is *not* considered a breaking
|
||||
change, but will not be done without good reasons. The latest 3 stable Rust
|
||||
versions will always be supported no matter what.
|
||||
13
clamav/libclamav_rust/.cargo/vendor/adler/RELEASE_PROCESS.md
vendored
Normal file
13
clamav/libclamav_rust/.cargo/vendor/adler/RELEASE_PROCESS.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# What to do to publish a new release
|
||||
|
||||
1. Ensure all notable changes are in the changelog under "Unreleased".
|
||||
|
||||
2. Execute `cargo release <level>` to bump version(s), tag and publish
|
||||
everything. External subcommand, must be installed with `cargo install
|
||||
cargo-release`.
|
||||
|
||||
`<level>` can be one of `major|minor|patch`. If this is the first release
|
||||
(`0.1.0`), use `minor`, since the version starts out as `0.0.0`.
|
||||
|
||||
3. Go to the GitHub releases, edit the just-pushed tag. Copy the release notes
|
||||
from the changelog.
|
||||
109
clamav/libclamav_rust/.cargo/vendor/adler/benches/bench.rs
vendored
Normal file
109
clamav/libclamav_rust/.cargo/vendor/adler/benches/bench.rs
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
extern crate adler;
|
||||
extern crate criterion;
|
||||
|
||||
use adler::{adler32_slice, Adler32};
|
||||
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
|
||||
|
||||
fn simple(c: &mut Criterion) {
|
||||
{
|
||||
const SIZE: usize = 100;
|
||||
|
||||
let mut group = c.benchmark_group("simple-100b");
|
||||
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||
group.bench_function("zeroes-100", |bencher| {
|
||||
bencher.iter(|| {
|
||||
adler32_slice(&[0; SIZE]);
|
||||
});
|
||||
});
|
||||
group.bench_function("ones-100", |bencher| {
|
||||
bencher.iter(|| {
|
||||
adler32_slice(&[0xff; SIZE]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const SIZE: usize = 1024;
|
||||
|
||||
let mut group = c.benchmark_group("simple-1k");
|
||||
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||
|
||||
group.bench_function("zeroes-1k", |bencher| {
|
||||
bencher.iter(|| {
|
||||
adler32_slice(&[0; SIZE]);
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_function("ones-1k", |bencher| {
|
||||
bencher.iter(|| {
|
||||
adler32_slice(&[0xff; SIZE]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const SIZE: usize = 1024 * 1024;
|
||||
|
||||
let mut group = c.benchmark_group("simple-1m");
|
||||
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||
group.bench_function("zeroes-1m", |bencher| {
|
||||
bencher.iter(|| {
|
||||
adler32_slice(&[0; SIZE]);
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_function("ones-1m", |bencher| {
|
||||
bencher.iter(|| {
|
||||
adler32_slice(&[0xff; SIZE]);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn chunked(c: &mut Criterion) {
|
||||
const SIZE: usize = 16 * 1024 * 1024;
|
||||
|
||||
let data = vec![0xAB; SIZE];
|
||||
|
||||
let mut group = c.benchmark_group("chunked-16m");
|
||||
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||
group.bench_function("5552", |bencher| {
|
||||
bencher.iter(|| {
|
||||
let mut h = Adler32::new();
|
||||
for chunk in data.chunks(5552) {
|
||||
h.write_slice(chunk);
|
||||
}
|
||||
h.checksum()
|
||||
});
|
||||
});
|
||||
group.bench_function("8k", |bencher| {
|
||||
bencher.iter(|| {
|
||||
let mut h = Adler32::new();
|
||||
for chunk in data.chunks(8 * 1024) {
|
||||
h.write_slice(chunk);
|
||||
}
|
||||
h.checksum()
|
||||
});
|
||||
});
|
||||
group.bench_function("64k", |bencher| {
|
||||
bencher.iter(|| {
|
||||
let mut h = Adler32::new();
|
||||
for chunk in data.chunks(64 * 1024) {
|
||||
h.write_slice(chunk);
|
||||
}
|
||||
h.checksum()
|
||||
});
|
||||
});
|
||||
group.bench_function("1m", |bencher| {
|
||||
bencher.iter(|| {
|
||||
let mut h = Adler32::new();
|
||||
for chunk in data.chunks(1024 * 1024) {
|
||||
h.write_slice(chunk);
|
||||
}
|
||||
h.checksum()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, simple, chunked);
|
||||
criterion_main!(benches);
|
||||
146
clamav/libclamav_rust/.cargo/vendor/adler/src/algo.rs
vendored
Normal file
146
clamav/libclamav_rust/.cargo/vendor/adler/src/algo.rs
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
use crate::Adler32;
|
||||
use std::ops::{AddAssign, MulAssign, RemAssign};
|
||||
|
||||
impl Adler32 {
|
||||
pub(crate) fn compute(&mut self, bytes: &[u8]) {
|
||||
// The basic algorithm is, for every byte:
|
||||
// a = (a + byte) % MOD
|
||||
// b = (b + a) % MOD
|
||||
// where MOD = 65521.
|
||||
//
|
||||
// For efficiency, we can defer the `% MOD` operations as long as neither a nor b overflows:
|
||||
// - Between calls to `write`, we ensure that a and b are always in range 0..MOD.
|
||||
// - We use 32-bit arithmetic in this function.
|
||||
// - Therefore, a and b must not increase by more than 2^32-MOD without performing a `% MOD`
|
||||
// operation.
|
||||
//
|
||||
// According to Wikipedia, b is calculated as follows for non-incremental checksumming:
|
||||
// b = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n*1 (mod 65521)
|
||||
// Where n is the number of bytes and Di is the i-th Byte. We need to change this to account
|
||||
// for the previous values of a and b, as well as treat every input Byte as being 255:
|
||||
// b_inc = n×255 + (n-1)×255 + ... + 255 + n*65520
|
||||
// Or in other words:
|
||||
// b_inc = n*65520 + n(n+1)/2*255
|
||||
// The max chunk size is thus the largest value of n so that b_inc <= 2^32-65521.
|
||||
// 2^32-65521 = n*65520 + n(n+1)/2*255
|
||||
// Plugging this into an equation solver since I can't math gives n = 5552.18..., so 5552.
|
||||
//
|
||||
// On top of the optimization outlined above, the algorithm can also be parallelized with a
|
||||
// bit more work:
|
||||
//
|
||||
// Note that b is a linear combination of a vector of input bytes (D1, ..., Dn).
|
||||
//
|
||||
// If we fix some value k<N and rewrite indices 1, ..., N as
|
||||
//
|
||||
// 1_1, 1_2, ..., 1_k, 2_1, ..., 2_k, ..., (N/k)_k,
|
||||
//
|
||||
// then we can express a and b in terms of sums of smaller sequences kb and ka:
|
||||
//
|
||||
// ka(j) := D1_j + D2_j + ... + D(N/k)_j where j <= k
|
||||
// kb(j) := (N/k)*D1_j + (N/k-1)*D2_j + ... + D(N/k)_j where j <= k
|
||||
//
|
||||
// a = ka(1) + ka(2) + ... + ka(k) + 1
|
||||
// b = k*(kb(1) + kb(2) + ... + kb(k)) - 1*ka(2) - ... - (k-1)*ka(k) + N
|
||||
//
|
||||
// We use this insight to unroll the main loop and process k=4 bytes at a time.
|
||||
// The resulting code is highly amenable to SIMD acceleration, although the immediate speedups
|
||||
// stem from increased pipeline parallelism rather than auto-vectorization.
|
||||
//
|
||||
// This technique is described in-depth (here:)[https://software.intel.com/content/www/us/\
|
||||
// en/develop/articles/fast-computation-of-fletcher-checksums.html]
|
||||
|
||||
const MOD: u32 = 65521;
|
||||
const CHUNK_SIZE: usize = 5552 * 4;
|
||||
|
||||
let mut a = u32::from(self.a);
|
||||
let mut b = u32::from(self.b);
|
||||
let mut a_vec = U32X4([0; 4]);
|
||||
let mut b_vec = a_vec;
|
||||
|
||||
let (bytes, remainder) = bytes.split_at(bytes.len() - bytes.len() % 4);
|
||||
|
||||
// iterate over 4 bytes at a time
|
||||
let chunk_iter = bytes.chunks_exact(CHUNK_SIZE);
|
||||
let remainder_chunk = chunk_iter.remainder();
|
||||
for chunk in chunk_iter {
|
||||
for byte_vec in chunk.chunks_exact(4) {
|
||||
let val = U32X4::from(byte_vec);
|
||||
a_vec += val;
|
||||
b_vec += a_vec;
|
||||
}
|
||||
b += CHUNK_SIZE as u32 * a;
|
||||
a_vec %= MOD;
|
||||
b_vec %= MOD;
|
||||
b %= MOD;
|
||||
}
|
||||
// special-case the final chunk because it may be shorter than the rest
|
||||
for byte_vec in remainder_chunk.chunks_exact(4) {
|
||||
let val = U32X4::from(byte_vec);
|
||||
a_vec += val;
|
||||
b_vec += a_vec;
|
||||
}
|
||||
b += remainder_chunk.len() as u32 * a;
|
||||
a_vec %= MOD;
|
||||
b_vec %= MOD;
|
||||
b %= MOD;
|
||||
|
||||
// combine the sub-sum results into the main sum
|
||||
b_vec *= 4;
|
||||
b_vec.0[1] += MOD - a_vec.0[1];
|
||||
b_vec.0[2] += (MOD - a_vec.0[2]) * 2;
|
||||
b_vec.0[3] += (MOD - a_vec.0[3]) * 3;
|
||||
for &av in a_vec.0.iter() {
|
||||
a += av;
|
||||
}
|
||||
for &bv in b_vec.0.iter() {
|
||||
b += bv;
|
||||
}
|
||||
|
||||
// iterate over the remaining few bytes in serial
|
||||
for &byte in remainder.iter() {
|
||||
a += u32::from(byte);
|
||||
b += a;
|
||||
}
|
||||
|
||||
self.a = (a % MOD) as u16;
|
||||
self.b = (b % MOD) as u16;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct U32X4([u32; 4]);
|
||||
|
||||
impl U32X4 {
|
||||
fn from(bytes: &[u8]) -> Self {
|
||||
U32X4([
|
||||
u32::from(bytes[0]),
|
||||
u32::from(bytes[1]),
|
||||
u32::from(bytes[2]),
|
||||
u32::from(bytes[3]),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Self> for U32X4 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
for (s, o) in self.0.iter_mut().zip(other.0.iter()) {
|
||||
*s += o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RemAssign<u32> for U32X4 {
|
||||
fn rem_assign(&mut self, quotient: u32) {
|
||||
for s in self.0.iter_mut() {
|
||||
*s %= quotient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<u32> for U32X4 {
|
||||
fn mul_assign(&mut self, rhs: u32) {
|
||||
for s in self.0.iter_mut() {
|
||||
*s *= rhs;
|
||||
}
|
||||
}
|
||||
}
|
||||
287
clamav/libclamav_rust/.cargo/vendor/adler/src/lib.rs
vendored
Normal file
287
clamav/libclamav_rust/.cargo/vendor/adler/src/lib.rs
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
//! Adler-32 checksum implementation.
|
||||
//!
|
||||
//! This implementation features:
|
||||
//!
|
||||
//! - Permissively licensed (0BSD) clean-room implementation.
|
||||
//! - Zero dependencies.
|
||||
//! - Zero `unsafe`.
|
||||
//! - Decent performance (3-4 GB/s).
|
||||
//! - `#![no_std]` support (with `default-features = false`).
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/adler/1.0.2")]
|
||||
// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default
|
||||
#![doc(test(attr(deny(unused_imports, unused_must_use))))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![forbid(unsafe_code)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate core as std;
|
||||
|
||||
mod algo;
|
||||
|
||||
use std::hash::Hasher;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::{self, BufRead};
|
||||
|
||||
/// Adler-32 checksum calculator.
|
||||
///
|
||||
/// An instance of this type is equivalent to an Adler-32 checksum: It can be created in the default
|
||||
/// state via [`new`] (or the provided `Default` impl), or from a precalculated checksum via
|
||||
/// [`from_checksum`], and the currently stored checksum can be fetched via [`checksum`].
|
||||
///
|
||||
/// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any
|
||||
/// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although
|
||||
/// that is not recommended (while every checksum is a hash function, they are not necessarily a
|
||||
/// good one).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic, piecewise checksum calculation:
|
||||
///
|
||||
/// ```
|
||||
/// use adler::Adler32;
|
||||
///
|
||||
/// let mut adler = Adler32::new();
|
||||
///
|
||||
/// adler.write_slice(&[0, 1, 2]);
|
||||
/// adler.write_slice(&[3, 4, 5]);
|
||||
///
|
||||
/// assert_eq!(adler.checksum(), 0x00290010);
|
||||
/// ```
|
||||
///
|
||||
/// Using `Hash` to process structures:
|
||||
///
|
||||
/// ```
|
||||
/// use std::hash::Hash;
|
||||
/// use adler::Adler32;
|
||||
///
|
||||
/// #[derive(Hash)]
|
||||
/// struct Data {
|
||||
/// byte: u8,
|
||||
/// word: u16,
|
||||
/// big: u64,
|
||||
/// }
|
||||
///
|
||||
/// let mut adler = Adler32::new();
|
||||
///
|
||||
/// let data = Data { byte: 0x1F, word: 0xABCD, big: !0 };
|
||||
/// data.hash(&mut adler);
|
||||
///
|
||||
/// // hash value depends on architecture endianness
|
||||
/// if cfg!(target_endian = "little") {
|
||||
/// assert_eq!(adler.checksum(), 0x33410990);
|
||||
/// }
|
||||
/// if cfg!(target_endian = "big") {
|
||||
/// assert_eq!(adler.checksum(), 0x331F0990);
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// [`new`]: #method.new
|
||||
/// [`from_checksum`]: #method.from_checksum
|
||||
/// [`checksum`]: #method.checksum
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Adler32 {
|
||||
a: u16,
|
||||
b: u16,
|
||||
}
|
||||
|
||||
impl Adler32 {
|
||||
/// Creates a new Adler-32 instance with default state.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Creates an `Adler32` instance from a precomputed Adler-32 checksum.
|
||||
///
|
||||
/// This allows resuming checksum calculation without having to keep the `Adler32` instance
|
||||
/// around.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use adler::Adler32;
|
||||
/// let parts = [
|
||||
/// "rust",
|
||||
/// "acean",
|
||||
/// ];
|
||||
/// let whole = adler::adler32_slice(b"rustacean");
|
||||
///
|
||||
/// let mut sum = Adler32::new();
|
||||
/// sum.write_slice(parts[0].as_bytes());
|
||||
/// let partial = sum.checksum();
|
||||
///
|
||||
/// // ...later
|
||||
///
|
||||
/// let mut sum = Adler32::from_checksum(partial);
|
||||
/// sum.write_slice(parts[1].as_bytes());
|
||||
/// assert_eq!(sum.checksum(), whole);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_checksum(sum: u32) -> Self {
|
||||
Adler32 {
|
||||
a: sum as u16,
|
||||
b: (sum >> 16) as u16,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the calculated checksum at this point in time.
|
||||
#[inline]
|
||||
pub fn checksum(&self) -> u32 {
|
||||
(u32::from(self.b) << 16) | u32::from(self.a)
|
||||
}
|
||||
|
||||
/// Adds `bytes` to the checksum calculation.
|
||||
///
|
||||
/// If efficiency matters, this should be called with Byte slices that contain at least a few
|
||||
/// thousand Bytes.
|
||||
pub fn write_slice(&mut self, bytes: &[u8]) {
|
||||
self.compute(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Adler32 {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Adler32 { a: 1, b: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Hasher for Adler32 {
|
||||
#[inline]
|
||||
fn finish(&self) -> u64 {
|
||||
u64::from(self.checksum())
|
||||
}
|
||||
|
||||
fn write(&mut self, bytes: &[u8]) {
|
||||
self.write_slice(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the Adler-32 checksum of a byte slice.
|
||||
///
|
||||
/// This is a convenience function around the [`Adler32`] type.
|
||||
///
|
||||
/// [`Adler32`]: struct.Adler32.html
|
||||
pub fn adler32_slice(data: &[u8]) -> u32 {
|
||||
let mut h = Adler32::new();
|
||||
h.write_slice(data);
|
||||
h.checksum()
|
||||
}
|
||||
|
||||
/// Calculates the Adler-32 checksum of a `BufRead`'s contents.
|
||||
///
|
||||
/// The passed `BufRead` implementor will be read until it reaches EOF (or until it reports an
|
||||
/// error).
|
||||
///
|
||||
/// If you only have a `Read` implementor, you can wrap it in `std::io::BufReader` before calling
|
||||
/// this function.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Any error returned by the reader are bubbled up by this function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use adler::adler32;
|
||||
///
|
||||
/// use std::fs::File;
|
||||
/// use std::io::BufReader;
|
||||
///
|
||||
/// let file = File::open("input.txt")?;
|
||||
/// let mut file = BufReader::new(file);
|
||||
///
|
||||
/// adler32(&mut file)?;
|
||||
/// # Ok(()) }
|
||||
/// # fn main() { run().unwrap() }
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
pub fn adler32<R: BufRead>(mut reader: R) -> io::Result<u32> {
|
||||
let mut h = Adler32::new();
|
||||
loop {
|
||||
let len = {
|
||||
let buf = reader.fill_buf()?;
|
||||
if buf.is_empty() {
|
||||
return Ok(h.checksum());
|
||||
}
|
||||
|
||||
h.write_slice(buf);
|
||||
buf.len()
|
||||
};
|
||||
reader.consume(len);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn zeroes() {
|
||||
assert_eq!(adler32_slice(&[]), 1);
|
||||
assert_eq!(adler32_slice(&[0]), 1 | 1 << 16);
|
||||
assert_eq!(adler32_slice(&[0, 0]), 1 | 2 << 16);
|
||||
assert_eq!(adler32_slice(&[0; 100]), 0x00640001);
|
||||
assert_eq!(adler32_slice(&[0; 1024]), 0x04000001);
|
||||
assert_eq!(adler32_slice(&[0; 1024 * 1024]), 0x00f00001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ones() {
|
||||
assert_eq!(adler32_slice(&[0xff; 1024]), 0x79a6fc2e);
|
||||
assert_eq!(adler32_slice(&[0xff; 1024 * 1024]), 0x8e88ef11);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed() {
|
||||
assert_eq!(adler32_slice(&[1]), 2 | 2 << 16);
|
||||
assert_eq!(adler32_slice(&[40]), 41 | 41 << 16);
|
||||
|
||||
assert_eq!(adler32_slice(&[0xA5; 1024 * 1024]), 0xd5009ab1);
|
||||
}
|
||||
|
||||
/// Example calculation from https://en.wikipedia.org/wiki/Adler-32.
|
||||
#[test]
|
||||
fn wiki() {
|
||||
assert_eq!(adler32_slice(b"Wikipedia"), 0x11E60398);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resume() {
|
||||
let mut adler = Adler32::new();
|
||||
adler.write_slice(&[0xff; 1024]);
|
||||
let partial = adler.checksum();
|
||||
assert_eq!(partial, 0x79a6fc2e); // from above
|
||||
adler.write_slice(&[0xff; 1024 * 1024 - 1024]);
|
||||
assert_eq!(adler.checksum(), 0x8e88ef11); // from above
|
||||
|
||||
// Make sure that we can resume computing from the partial checksum via `from_checksum`.
|
||||
let mut adler = Adler32::from_checksum(partial);
|
||||
adler.write_slice(&[0xff; 1024 * 1024 - 1024]);
|
||||
assert_eq!(adler.checksum(), 0x8e88ef11); // from above
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn bufread() {
|
||||
use std::io::BufReader;
|
||||
fn test(data: &[u8], checksum: u32) {
|
||||
// `BufReader` uses an 8 KB buffer, so this will test buffer refilling.
|
||||
let mut buf = BufReader::new(data);
|
||||
let real_sum = adler32(&mut buf).unwrap();
|
||||
assert_eq!(checksum, real_sum);
|
||||
}
|
||||
|
||||
test(&[], 1);
|
||||
test(&[0; 1024], 0x04000001);
|
||||
test(&[0; 1024 * 1024], 0x00f00001);
|
||||
test(&[0xA5; 1024 * 1024], 0xd5009ab1);
|
||||
}
|
||||
}
|
||||
1
clamav/libclamav_rust/.cargo/vendor/aho-corasick/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/aho-corasick/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"c9b1b15e299ba4e6ed0d6f25cde30b26b13b6068a7fbd980000c37bca19b0104","DESIGN.md":"64ff45ea2a89d4c32b29af91acb7743a861fcac417cb94fde8e6559405d603b2","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"5999e5768f5da8ab9b50c016766b5185b4c79936c56bef6d311ddcb0a38c4b94","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"b92c9a65c4ee8029ff5a710aa1514caf838e73072c177dff5375463769f0b1ce","src/automaton.rs":"931af0aad03079bc4f6400d573fce832ce1edeeaf196815a16750d57b54b2183","src/buffer.rs":"dae7ee7c1f846ca9cf115ba4949484000e1837b4fb7311f8d8c9a35011c9c26f","src/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/classes.rs":"99a53a2ed8eea8c13699def90e31dfdff9d0b90572b1db3cb534e3396e7a0ed0","src/dfa.rs":"25e4455b3e179a7e192108d05f3683993456b36e3ebed99f827558c52525b7e6","src/error.rs":"d34c2c9c815df5d9dedc46b4b3ce109cd2cee07825de643f0c574ec960367beb","src/lib.rs":"7a47d4c87f83e0e7ddf0777a71e4858904e73477ce18404cb89e656070e86aef","src/nfa.rs":"3b817b4aa85540e8c0d35aff7ed7cfbab70ec7d2aaa779d63b4f5369bff31ce1","src/packed/api.rs":"df42e7500c94c9de1ac44145a0dd99ea02047e6bba229da12f2575337beebcf0","src/packed/mod.rs":"ad2f8e18996737347a1181a4457387276d139315bcabfc5e34494af0c0319701","src/packed/pattern.rs":"3abf3835d4c4f8a43753c52936a894d819f713f233fc046e19de5ef95200dcce","src/packed/rabinkarp.rs":"ad7d4533f96aed336e29c5553657ae57b0d733ace9c707a6cf4d08d8fc6edee5","src/packed/teddy/README.md":"b4b83fb5afafbbea6cb76fe70f49cc8ced888f682d98abe5ea5773e95d9ec2b0","src/packed/teddy/compile.rs":"aad40b3f93d2c388b409b31fb2795d414a365237789d5b1a7510d97ceb8ce260","src/packed/teddy/mod.rs":"83b52bd80272970ad17234d0db293d17c1710ec582302bf516b203c8edec037e","src/packed/teddy/runtime.rs":"836146e90b320b14fa2c65fe4af7915a41f6fb04408aac5fac731c22ff46adae","src/packed/tests.rs":"b8dc4d3281ecd6d0fa2bf7ef16cf292a467dfdce64e470c7921e983bfa60fee2","src/packed/vector.rs":"ab3c0535fca5f09198d58cbfae44c292aeb3ce44bc92bca36d30dc72963639fc","src/prefilter.rs":"82a3eb6d5c0c3f10bc8d5f57d55d6d14cf4cf21c475bb5253e1921084063b8d7","src/state_id.rs":"519ec8c7bf3fa72103d4c561c193759759f535dca924c9853efe630f406d2029","src/tests.rs":"ee9b85f3c27cb2fba5796e5be8019aafecc13ee9a4f614553f2bc8953f51c6de"},"package":"cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"}
|
||||
3
clamav/libclamav_rust/.cargo/vendor/aho-corasick/COPYING
vendored
Normal file
3
clamav/libclamav_rust/.cargo/vendor/aho-corasick/COPYING
vendored
Normal file
@@ -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.
|
||||
50
clamav/libclamav_rust/.cargo/vendor/aho-corasick/Cargo.toml
vendored
Normal file
50
clamav/libclamav_rust/.cargo/vendor/aho-corasick/Cargo.toml
vendored
Normal file
@@ -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 = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
exclude = ["/aho-corasick-debug"]
|
||||
autotests = false
|
||||
description = "Fast multiple substring searching."
|
||||
homepage = "https://github.com/BurntSushi/aho-corasick"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"string",
|
||||
"search",
|
||||
"text",
|
||||
"aho",
|
||||
"multi",
|
||||
]
|
||||
categories = ["text-processing"]
|
||||
license = "Unlicense OR MIT"
|
||||
repository = "https://github.com/BurntSushi/aho-corasick"
|
||||
|
||||
[profile.bench]
|
||||
debug = true
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
[lib]
|
||||
name = "aho_corasick"
|
||||
|
||||
[dependencies.memchr]
|
||||
version = "2.4.0"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["memchr/std"]
|
||||
483
clamav/libclamav_rust/.cargo/vendor/aho-corasick/DESIGN.md
vendored
Normal file
483
clamav/libclamav_rust/.cargo/vendor/aho-corasick/DESIGN.md
vendored
Normal file
@@ -0,0 +1,483 @@
|
||||
This document describes the internal design of this crate, which is an object
|
||||
lesson in what happens when you take a fairly simple old algorithm like
|
||||
Aho-Corasick and make it fast and production ready.
|
||||
|
||||
The target audience of this document is Rust programmers that have some
|
||||
familiarity with string searching, however, one does not need to know the
|
||||
Aho-Corasick algorithm in order to read this (it is explained below). One
|
||||
should, however, know what a trie is. (If you don't, go read its Wikipedia
|
||||
article.)
|
||||
|
||||
The center-piece of this crate is an implementation of Aho-Corasick. On its
|
||||
own, Aho-Corasick isn't that complicated. The complex pieces come from the
|
||||
different variants of Aho-Corasick implemented in this crate. Specifically,
|
||||
they are:
|
||||
|
||||
* Aho-Corasick as an NFA, using dense transitions near the root with sparse
|
||||
transitions elsewhere.
|
||||
* Aho-Corasick as a DFA. (An NFA is slower to search, but cheaper to construct
|
||||
and uses less memory.)
|
||||
* A DFA with pre-multiplied state identifiers. This saves a multiplication
|
||||
instruction in the core search loop.
|
||||
* A DFA with equivalence classes of bytes as the alphabet, instead of the
|
||||
traditional 256-byte alphabet. This shrinks the size of the DFA in memory,
|
||||
but adds an extra lookup in the core search loop to map the input byte to
|
||||
an equivalent class.
|
||||
* The option to choose how state identifiers are represented, via one of
|
||||
u8, u16, u32, u64 or usize. This permits creating compact automatons when
|
||||
matching a small number of patterns.
|
||||
* Supporting "standard" match semantics, along with its overlapping variant,
|
||||
in addition to leftmost-first and leftmost-longest semantics. The "standard"
|
||||
semantics are typically what you see in a textbook description of
|
||||
Aho-Corasick. However, Aho-Corasick is also useful as an optimization in
|
||||
regex engines, which often use leftmost-first or leftmost-longest semantics.
|
||||
Thus, it is useful to implement those semantics here. The "standard" and
|
||||
"leftmost" search algorithms are subtly different, and also require slightly
|
||||
different construction algorithms.
|
||||
* Support for ASCII case insensitive matching.
|
||||
* Support for accelerating searches when the patterns all start with a small
|
||||
number of fixed bytes. Or alternatively, when the patterns all contain a
|
||||
small number of rare bytes. (Searching for these bytes uses SIMD vectorized
|
||||
code courtesy of `memchr`.)
|
||||
* Transparent support for alternative SIMD vectorized search routines for
|
||||
smaller number of literals, such as the Teddy algorithm. We called these
|
||||
"packed" search routines because they use SIMD. They can often be an order of
|
||||
magnitude faster than just Aho-Corasick, but don't scale as well.
|
||||
* Support for searching streams. This can reuse most of the underlying code,
|
||||
but does require careful buffering support.
|
||||
* Support for anchored searches, which permit efficient `is_prefix` checks for
|
||||
a large number of patterns.
|
||||
|
||||
When you combine all of this together along with trying to make everything as
|
||||
fast as possible, what you end up with is enitrely too much code with too much
|
||||
`unsafe`. Alas, I was not smart enough to figure out how to reduce it. Instead,
|
||||
we will explain it.
|
||||
|
||||
|
||||
# Basics
|
||||
|
||||
The fundamental problem this crate is trying to solve is to determine the
|
||||
occurrences of possibly many patterns in a haystack. The naive way to solve
|
||||
this is to look for a match for each pattern at each position in the haystack:
|
||||
|
||||
for i in 0..haystack.len():
|
||||
for p in patterns.iter():
|
||||
if haystack[i..].starts_with(p.bytes()):
|
||||
return Match(p.id(), i, i + p.bytes().len())
|
||||
|
||||
Those four lines are effectively all this crate does. The problem with those
|
||||
four lines is that they are very slow, especially when you're searching for a
|
||||
large number of patterns.
|
||||
|
||||
While there are many different algorithms available to solve this, a popular
|
||||
one is Aho-Corasick. It's a common solution because it's not too hard to
|
||||
implement, scales quite well even when searching for thousands of patterns and
|
||||
is generally pretty fast. Aho-Corasick does well here because, regardless of
|
||||
the number of patterns you're searching for, it always visits each byte in the
|
||||
haystack exactly once. This means, generally speaking, adding more patterns to
|
||||
an Aho-Corasick automaton does not make it slower. (Strictly speaking, however,
|
||||
this is not true, since a larger automaton will make less effective use of the
|
||||
CPU's cache.)
|
||||
|
||||
Aho-Corasick can be succinctly described as a trie with state transitions
|
||||
between some of the nodes that efficiently instruct the search algorithm to
|
||||
try matching alternative keys in the automaton. The trick is that these state
|
||||
transitions are arranged such that each byte of input needs to be inspected
|
||||
only once. These state transitions are typically called "failure transitions,"
|
||||
because they instruct the searcher (the thing traversing the automaton while
|
||||
reading from the haystack) what to do when a byte in the haystack does not
|
||||
correspond to a valid transition in the current state of the trie.
|
||||
|
||||
More formally, a failure transition points to a state in the automaton that may
|
||||
lead to a match whose prefix is a proper suffix of the path traversed through
|
||||
the trie so far. (If no such proper suffix exists, then the failure transition
|
||||
points back to the start state of the trie, effectively restarting the search.)
|
||||
This is perhaps simpler to explain pictorally. For example, let's say we built
|
||||
an Aho-Corasick automaton with the following patterns: 'abcd' and 'cef'. The
|
||||
trie looks like this:
|
||||
|
||||
a - S1 - b - S2 - c - S3 - d - S4*
|
||||
/
|
||||
S0 - c - S5 - e - S6 - f - S7*
|
||||
|
||||
where states marked with a `*` are match states (meaning, the search algorithm
|
||||
should stop and report a match to the caller).
|
||||
|
||||
So given this trie, it should be somewhat straight-forward to see how it can
|
||||
be used to determine whether any particular haystack *starts* with either
|
||||
`abcd` or `cef`. It's easy to express this in code:
|
||||
|
||||
fn has_prefix(trie: &Trie, haystack: &[u8]) -> bool {
|
||||
let mut state_id = trie.start();
|
||||
// If the empty pattern is in trie, then state_id is a match state.
|
||||
if trie.is_match(state_id) {
|
||||
return true;
|
||||
}
|
||||
for (i, &b) in haystack.iter().enumerate() {
|
||||
state_id = match trie.next_state(state_id, b) {
|
||||
Some(id) => id,
|
||||
// If there was no transition for this state and byte, then we know
|
||||
// the haystack does not start with one of the patterns in our trie.
|
||||
None => return false,
|
||||
};
|
||||
if trie.is_match(state_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
And that's pretty much it. All we do is move through the trie starting with the
|
||||
bytes at the beginning of the haystack. If we find ourselves in a position
|
||||
where we can't move, or if we've looked through the entire haystack without
|
||||
seeing a match state, then we know the haystack does not start with any of the
|
||||
patterns in the trie.
|
||||
|
||||
The meat of the Aho-Corasick algorithm is in how we add failure transitions to
|
||||
our trie to keep searching efficient. Specifically, it permits us to not only
|
||||
check whether a haystack *starts* with any one of a number of patterns, but
|
||||
rather, whether the haystack contains any of a number of patterns *anywhere* in
|
||||
the haystack.
|
||||
|
||||
As mentioned before, failure transitions connect a proper suffix of the path
|
||||
traversed through the trie before, with a path that leads to a match that has a
|
||||
prefix corresponding to that proper suffix. So in our case, for patterns `abcd`
|
||||
and `cef`, with a haystack `abcef`, we want to transition to state `S5` (from
|
||||
the diagram above) from `S3` upon seeing that the byte following `c` is not
|
||||
`d`. Namely, the proper suffix in this example is `c`, which is a prefix of
|
||||
`cef`. So the modified diagram looks like this:
|
||||
|
||||
|
||||
a - S1 - b - S2 - c - S3 - d - S4*
|
||||
/ /
|
||||
/ ----------------
|
||||
/ /
|
||||
S0 - c - S5 - e - S6 - f - S7*
|
||||
|
||||
One thing that isn't shown in this diagram is that *all* states have a failure
|
||||
transition, but only `S3` has a *non-trivial* failure transition. That is, all
|
||||
other states have a failure transition back to the start state. So if our
|
||||
haystack was `abzabcd`, then the searcher would transition back to `S0` after
|
||||
seeing `z`, which effectively restarts the search. (Because there is no pattern
|
||||
in our trie that has a prefix of `bz` or `z`.)
|
||||
|
||||
The code for traversing this *automaton* or *finite state machine* (it is no
|
||||
longer just a trie) is not that much different from the `has_prefix` code
|
||||
above:
|
||||
|
||||
fn contains(fsm: &FiniteStateMachine, haystack: &[u8]) -> bool {
|
||||
let mut state_id = fsm.start();
|
||||
// If the empty pattern is in fsm, then state_id is a match state.
|
||||
if fsm.is_match(state_id) {
|
||||
return true;
|
||||
}
|
||||
for (i, &b) in haystack.iter().enumerate() {
|
||||
// While the diagram above doesn't show this, we may wind up needing
|
||||
// to follow multiple failure transitions before we land on a state
|
||||
// in which we can advance. Therefore, when searching for the next
|
||||
// state, we need to loop until we don't see a failure transition.
|
||||
//
|
||||
// This loop terminates because the start state has no empty
|
||||
// transitions. Every transition from the start state either points to
|
||||
// another state, or loops back to the start state.
|
||||
loop {
|
||||
match fsm.next_state(state_id, b) {
|
||||
Some(id) => {
|
||||
state_id = id;
|
||||
break;
|
||||
}
|
||||
// Unlike our code above, if there was no transition for this
|
||||
// state, then we don't quit. Instead, we look for this state's
|
||||
// failure transition and follow that instead.
|
||||
None => {
|
||||
state_id = fsm.next_fail_state(state_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
if fsm.is_match(state_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
Other than the complication around traversing failure transitions, this code
|
||||
is still roughly "traverse the automaton with bytes from the haystack, and quit
|
||||
when a match is seen."
|
||||
|
||||
And that concludes our section on the basics. While we didn't go deep into
|
||||
how the automaton is built (see `src/nfa.rs`, which has detailed comments about
|
||||
that), the basic structure of Aho-Corasick should be reasonably clear.
|
||||
|
||||
|
||||
# NFAs and DFAs
|
||||
|
||||
There are generally two types of finite automata: non-deterministic finite
|
||||
automata (NFA) and deterministic finite automata (DFA). The difference between
|
||||
them is, principally, that an NFA can be in multiple states at once. This is
|
||||
typically accomplished by things called _epsilon_ transitions, where one could
|
||||
move to a new state without consuming any bytes from the input. (The other
|
||||
mechanism by which NFAs can be in more than one state is where the same byte in
|
||||
a particular state transitions to multiple distinct states.) In contrast, a DFA
|
||||
can only ever be in one state at a time. A DFA has no epsilon transitions, and
|
||||
for any given state, a byte transitions to at most one other state.
|
||||
|
||||
By this formulation, the Aho-Corasick automaton described in the previous
|
||||
section is an NFA. This is because failure transitions are, effectively,
|
||||
epsilon transitions. That is, whenever the automaton is in state `S`, it is
|
||||
actually in the set of states that are reachable by recursively following
|
||||
failure transitions from `S`. (This means that, for example, the start state
|
||||
is always active since the start state is reachable via failure transitions
|
||||
from any state in the automaton.)
|
||||
|
||||
NFAs have a lot of nice properties. They tend to be easier to construct, and
|
||||
also tend to use less memory. However, their primary downside is that they are
|
||||
typically slower to execute. For example, the code above showing how to search
|
||||
with an Aho-Corasick automaton needs to potentially iterate through many
|
||||
failure transitions for every byte of input. While this is a fairly small
|
||||
amount of overhead, this can add up, especially if the automaton has a lot of
|
||||
overlapping patterns with a lot of failure transitions.
|
||||
|
||||
A DFA's search code, by contrast, looks like this:
|
||||
|
||||
fn contains(dfa: &DFA, haystack: &[u8]) -> bool {
|
||||
let mut state_id = dfa.start();
|
||||
// If the empty pattern is in dfa, then state_id is a match state.
|
||||
if dfa.is_match(state_id) {
|
||||
return true;
|
||||
}
|
||||
for (i, &b) in haystack.iter().enumerate() {
|
||||
// An Aho-Corasick DFA *never* has a missing state that requires
|
||||
// failure transitions to be followed. One byte of input advances the
|
||||
// automaton by one state. Always.
|
||||
state_id = dfa.next_state(state_id, b);
|
||||
if dfa.is_match(state_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
The search logic here is much simpler than for the NFA, and this tends to
|
||||
translate into significant performance benefits as well, since there's a lot
|
||||
less work being done for each byte in the haystack. How is this accomplished?
|
||||
It's done by pre-following all failure transitions for all states for all bytes
|
||||
in the alphabet, and then building a single state transition table. Building
|
||||
this DFA can be much more costly than building the NFA, and use much more
|
||||
memory, but the better performance can be worth it.
|
||||
|
||||
Users of this crate can actually choose between using an NFA or a DFA. By
|
||||
default, an NFA is used, because it typically strikes the best balance between
|
||||
space usage and search performance. But the DFA option is available for cases
|
||||
where a little extra memory and upfront time building the automaton is okay.
|
||||
For example, the `AhoCorasick::auto_configure` and
|
||||
`AhoCorasickBuilder::auto_configure` methods will enable the DFA setting if
|
||||
there are a small number of patterns.
|
||||
|
||||
|
||||
# More DFA tricks
|
||||
|
||||
As described in the previous section, one of the downsides of using a DFA
|
||||
is that it uses more memory and can take longer to build. One small way of
|
||||
mitigating these concerns is to map the alphabet used by the automaton into
|
||||
a smaller space. Typically, the alphabet of a DFA has 256 elements in it:
|
||||
one element for each possible value that fits into a byte. However, in many
|
||||
cases, one does not need the full alphabet. For example, if all patterns in an
|
||||
Aho-Corasick automaton are ASCII letters, then this only uses up 52 distinct
|
||||
bytes. As far as the automaton is concerned, the rest of the 204 bytes are
|
||||
indistinguishable from one another: they will never disrciminate between a
|
||||
match or a non-match. Therefore, in cases like that, the alphabet can be shrunk
|
||||
to just 53 elements. One for each ASCII letter, and then another to serve as a
|
||||
placeholder for every other unused byte.
|
||||
|
||||
In practice, this library doesn't quite compute the optimal set of equivalence
|
||||
classes, but it's close enough in most cases. The key idea is that this then
|
||||
allows the transition table for the DFA to be potentially much smaller. The
|
||||
downside of doing this, however, is that since the transition table is defined
|
||||
in terms of this smaller alphabet space, every byte in the haystack must be
|
||||
re-mapped to this smaller space. This requires an additional 256-byte table.
|
||||
In practice, this can lead to a small search time hit, but it can be difficult
|
||||
to measure. Moreover, it can sometimes lead to faster search times for bigger
|
||||
automata, since it could be difference between more parts of the automaton
|
||||
staying in the CPU cache or not.
|
||||
|
||||
One other trick for DFAs employed by this crate is the notion of premultiplying
|
||||
state identifiers. Specifically, the normal way to compute the next transition
|
||||
in a DFA is via the following (assuming that the transition table is laid out
|
||||
sequentially in memory, in row-major order, where the rows are states):
|
||||
|
||||
next_state_id = dfa.transitions[current_state_id * 256 + current_byte]
|
||||
|
||||
However, since the value `256` is a fixed constant, we can actually premultiply
|
||||
the state identifiers in the table when we build the table initially. Then, the
|
||||
next transition computation simply becomes:
|
||||
|
||||
next_state_id = dfa.transitions[current_state_id + current_byte]
|
||||
|
||||
This doesn't seem like much, but when this is being executed for every byte of
|
||||
input that you're searching, saving that extra multiplication instruction can
|
||||
add up.
|
||||
|
||||
The same optimization works even when equivalence classes are enabled, as
|
||||
described above. The only difference is that the premultiplication is by the
|
||||
total number of equivalence classes instead of 256.
|
||||
|
||||
There isn't much downside to premultiplying state identifiers, other than the
|
||||
fact that you may need to choose a bigger integer representation than you would
|
||||
otherwise. For example, if you don't premultiply state identifiers, then an
|
||||
automaton that uses `u8` as a state identifier can hold up to 256 states.
|
||||
However, if they are premultiplied, then it can only hold up to
|
||||
`floor(256 / len(alphabet))` states. Thus premultiplication impacts how compact
|
||||
your DFA can be. In practice, it's pretty rare to use `u8` as a state
|
||||
identifier, so premultiplication is usually a good thing to do.
|
||||
|
||||
Both equivalence classes and premultiplication are tuneable parameters via the
|
||||
`AhoCorasickBuilder` type, and both are enabled by default.
|
||||
|
||||
|
||||
# Match semantics
|
||||
|
||||
One of the more interesting things about this implementation of Aho-Corasick
|
||||
that (as far as this author knows) separates it from other implementations, is
|
||||
that it natively supports leftmost-first and leftmost-longest match semantics.
|
||||
Briefly, match semantics refer to the decision procedure by which searching
|
||||
will disambiguate matches when there are multiple to choose from:
|
||||
|
||||
* **standard** match semantics emits matches as soon as they are detected by
|
||||
the automaton. This is typically equivalent to the textbook non-overlapping
|
||||
formulation of Aho-Corasick.
|
||||
* **leftmost-first** match semantics means that 1) the next match is the match
|
||||
starting at the leftmost position and 2) among multiple matches starting at
|
||||
the same leftmost position, the match corresponding to the pattern provided
|
||||
first by the caller is reported.
|
||||
* **leftmost-longest** is like leftmost-first, except when there are multiple
|
||||
matches starting at the same leftmost position, the pattern corresponding to
|
||||
the longest match is returned.
|
||||
|
||||
(The crate API documentation discusses these differences, with examples, in
|
||||
more depth on the `MatchKind` type.)
|
||||
|
||||
The reason why supporting these match semantics is important is because it
|
||||
gives the user more control over the match procedure. For example,
|
||||
leftmost-first permits users to implement match priority by simply putting the
|
||||
higher priority patterns first. Leftmost-longest, on the other hand, permits
|
||||
finding the longest possible match, which might be useful when trying to find
|
||||
words matching a dictionary. Additionally, regex engines often want to use
|
||||
Aho-Corasick as an optimization when searching for an alternation of literals.
|
||||
In order to preserve correct match semantics, regex engines typically can't use
|
||||
the standard textbook definition directly, since regex engines will implement
|
||||
either leftmost-first (Perl-like) or leftmost-longest (POSIX) match semantics.
|
||||
|
||||
Supporting leftmost semantics requires a couple key changes:
|
||||
|
||||
* Constructing the Aho-Corasick automaton changes a bit in both how the trie is
|
||||
constructed and how failure transitions are found. Namely, only a subset of
|
||||
the failure transitions are added. Specifically, only the failure transitions
|
||||
that either do not occur after a match or do occur after a match but preserve
|
||||
that match are kept. (More details on this can be found in `src/nfa.rs`.)
|
||||
* The search algorithm changes slightly. Since we are looking for the leftmost
|
||||
match, we cannot quit as soon as a match is detected. Instead, after a match
|
||||
is detected, we must keep searching until either the end of the input or
|
||||
until a dead state is seen. (Dead states are not used for standard match
|
||||
semantics. Dead states mean that searching should stop after a match has been
|
||||
found.)
|
||||
|
||||
Other implementations of Aho-Corasick do support leftmost match semantics, but
|
||||
they do it with more overhead at search time, or even worse, with a queue of
|
||||
matches and sophisticated hijinks to disambiguate the matches. While our
|
||||
construction algorithm becomes a bit more complicated, the correct match
|
||||
semantics fall out from the structure of the automaton itself.
|
||||
|
||||
|
||||
# Overlapping matches
|
||||
|
||||
One of the nice properties of an Aho-Corasick automaton is that it can report
|
||||
all possible matches, even when they overlap with one another. In this mode,
|
||||
the match semantics don't matter, since all possible matches are reported.
|
||||
Overlapping searches work just like regular searches, except the state
|
||||
identifier at which the previous search left off is carried over to the next
|
||||
search, so that it can pick up where it left off. If there are additional
|
||||
matches at that state, then they are reported before resuming the search.
|
||||
|
||||
Enabling leftmost-first or leftmost-longest match semantics causes the
|
||||
automaton to use a subset of all failure transitions, which means that
|
||||
overlapping searches cannot be used. Therefore, if leftmost match semantics are
|
||||
used, attempting to do an overlapping search will panic. Thus, to get
|
||||
overlapping searches, the caller must use the default standard match semantics.
|
||||
This behavior was chosen because there are only two alternatives, which were
|
||||
deemed worse:
|
||||
|
||||
* Compile two automatons internally, one for standard semantics and one for
|
||||
the semantics requested by the caller (if not standard).
|
||||
* Create a new type, distinct from the `AhoCorasick` type, which has different
|
||||
capabilities based on the configuration options.
|
||||
|
||||
The first is untenable because of the amount of memory used by the automaton.
|
||||
The second increases the complexity of the API too much by adding too many
|
||||
types that do similar things. It is conceptually much simpler to keep all
|
||||
searching isolated to a single type. Callers may query whether the automaton
|
||||
supports overlapping searches via the `AhoCorasick::supports_overlapping`
|
||||
method.
|
||||
|
||||
|
||||
# Stream searching
|
||||
|
||||
Since Aho-Corasick is an automaton, it is possible to do partial searches on
|
||||
partial parts of the haystack, and then resume that search on subsequent pieces
|
||||
of the haystack. This is useful when the haystack you're trying to search is
|
||||
not stored contiguously in memory, or if one does not want to read the entire
|
||||
haystack into memory at once.
|
||||
|
||||
Currently, only standard semantics are supported for stream searching. This is
|
||||
some of the more complicated code in this crate, and is something I would very
|
||||
much like to improve. In particular, it currently has the restriction that it
|
||||
must buffer at least enough of the haystack in memory in order to fit the
|
||||
longest possible match. The difficulty in getting stream searching right is
|
||||
that the implementation choices (such as the buffer size) often impact what the
|
||||
API looks like and what it's allowed to do.
|
||||
|
||||
|
||||
# Prefilters
|
||||
|
||||
In some cases, Aho-Corasick is not the fastest way to find matches containing
|
||||
multiple patterns. Sometimes, the search can be accelerated using highly
|
||||
optimized SIMD routines. For example, consider searching the following
|
||||
patterns:
|
||||
|
||||
Sherlock
|
||||
Moriarty
|
||||
Watson
|
||||
|
||||
It is plausible that it would be much faster to quickly look for occurrences of
|
||||
the leading bytes, `S`, `M` or `W`, before trying to start searching via the
|
||||
automaton. Indeed, this is exactly what this crate will do.
|
||||
|
||||
When there are more than three distinct starting bytes, then this crate will
|
||||
look for three distinct bytes occurring at any position in the patterns, while
|
||||
preferring bytes that are heuristically determined to be rare over others. For
|
||||
example:
|
||||
|
||||
Abuzz
|
||||
Sanchez
|
||||
Vasquez
|
||||
Topaz
|
||||
Waltz
|
||||
|
||||
Here, we have more than 3 distinct starting bytes, but all of the patterns
|
||||
contain `z`, which is typically a rare byte. In this case, the prefilter will
|
||||
scan for `z`, back up a bit, and then execute the Aho-Corasick automaton.
|
||||
|
||||
If all of that fails, then a packed multiple substring algorithm will be
|
||||
attempted. Currently, the only algorithm available for this is Teddy, but more
|
||||
may be added in the future. Teddy is unlike the above prefilters in that it
|
||||
confirms its own matches, so when Teddy is active, it might not be necessary
|
||||
for Aho-Corasick to run at all. (See `Automaton::leftmost_find_at_no_state_imp`
|
||||
in `src/automaton.rs`.) However, the current Teddy implementation only works
|
||||
in `x86_64` and when SSSE3 or AVX2 are available, and moreover, only works
|
||||
_well_ when there are a small number of patterns (say, less than 100). Teddy
|
||||
also requires the haystack to be of a certain length (more than 16-34 bytes).
|
||||
When the haystack is shorter than that, Rabin-Karp is used instead. (See
|
||||
`src/packed/rabinkarp.rs`.)
|
||||
|
||||
There is a more thorough description of Teddy at
|
||||
[`src/packed/teddy/README.md`](src/packed/teddy/README.md).
|
||||
21
clamav/libclamav_rust/.cargo/vendor/aho-corasick/LICENSE-MIT
vendored
Normal file
21
clamav/libclamav_rust/.cargo/vendor/aho-corasick/LICENSE-MIT
vendored
Normal file
@@ -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.
|
||||
187
clamav/libclamav_rust/.cargo/vendor/aho-corasick/README.md
vendored
Normal file
187
clamav/libclamav_rust/.cargo/vendor/aho-corasick/README.md
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
aho-corasick
|
||||
============
|
||||
A library for finding occurrences of many patterns at once with SIMD
|
||||
acceleration in some cases. This library provides multiple pattern
|
||||
search principally through an implementation of the
|
||||
[Aho-Corasick algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm),
|
||||
which builds a finite state machine for executing searches in linear time.
|
||||
Features include case insensitive matching, overlapping matches, fast searching
|
||||
via SIMD and optional full DFA construction and search & replace in streams.
|
||||
|
||||
[](https://github.com/BurntSushi/aho-corasick/actions)
|
||||
[](https://crates.io/crates/aho-corasick)
|
||||
|
||||
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
https://docs.rs/aho-corasick
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
aho-corasick = "0.7"
|
||||
```
|
||||
|
||||
|
||||
### Example: basic searching
|
||||
|
||||
This example shows how to search for occurrences of multiple patterns
|
||||
simultaneously. Each match includes the pattern that matched along with the
|
||||
byte offsets of the match.
|
||||
|
||||
```rust
|
||||
use aho_corasick::AhoCorasick;
|
||||
|
||||
let patterns = &["apple", "maple", "Snapple"];
|
||||
let haystack = "Nobody likes maple in their apple flavored Snapple.";
|
||||
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
let mut matches = vec![];
|
||||
for mat in ac.find_iter(haystack) {
|
||||
matches.push((mat.pattern(), mat.start(), mat.end()));
|
||||
}
|
||||
assert_eq!(matches, vec![
|
||||
(1, 13, 18),
|
||||
(0, 28, 33),
|
||||
(2, 43, 50),
|
||||
]);
|
||||
```
|
||||
|
||||
|
||||
### Example: case insensitivity
|
||||
|
||||
This is like the previous example, but matches `Snapple` case insensitively
|
||||
using `AhoCorasickBuilder`:
|
||||
|
||||
```rust
|
||||
use aho_corasick::AhoCorasickBuilder;
|
||||
|
||||
let patterns = &["apple", "maple", "snapple"];
|
||||
let haystack = "Nobody likes maple in their apple flavored Snapple.";
|
||||
|
||||
let ac = AhoCorasickBuilder::new()
|
||||
.ascii_case_insensitive(true)
|
||||
.build(patterns);
|
||||
let mut matches = vec![];
|
||||
for mat in ac.find_iter(haystack) {
|
||||
matches.push((mat.pattern(), mat.start(), mat.end()));
|
||||
}
|
||||
assert_eq!(matches, vec![
|
||||
(1, 13, 18),
|
||||
(0, 28, 33),
|
||||
(2, 43, 50),
|
||||
]);
|
||||
```
|
||||
|
||||
|
||||
### Example: replacing matches in a stream
|
||||
|
||||
This example shows how to execute a search and replace on a stream without
|
||||
loading the entire stream into memory first.
|
||||
|
||||
```rust
|
||||
use aho_corasick::AhoCorasick;
|
||||
|
||||
let patterns = &["fox", "brown", "quick"];
|
||||
let replace_with = &["sloth", "grey", "slow"];
|
||||
|
||||
// In a real example, these might be `std::fs::File`s instead. All you need to
|
||||
// do is supply a pair of `std::io::Read` and `std::io::Write` implementations.
|
||||
let rdr = "The quick brown fox.";
|
||||
let mut wtr = vec![];
|
||||
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
ac.stream_replace_all(rdr.as_bytes(), &mut wtr, replace_with)
|
||||
.expect("stream_replace_all failed");
|
||||
assert_eq!(b"The slow grey sloth.".to_vec(), wtr);
|
||||
```
|
||||
|
||||
|
||||
### Example: finding the leftmost first match
|
||||
|
||||
In the textbook description of Aho-Corasick, its formulation is typically
|
||||
structured such that it reports all possible matches, even when they overlap
|
||||
with another. In many cases, overlapping matches may not be desired, such as
|
||||
the case of finding all successive non-overlapping matches like you might with
|
||||
a standard regular expression.
|
||||
|
||||
Unfortunately the "obvious" way to modify the Aho-Corasick algorithm to do
|
||||
this doesn't always work in the expected way, since it will report matches as
|
||||
soon as they are seen. For example, consider matching the regex `Samwise|Sam`
|
||||
against the text `Samwise`. Most regex engines (that are Perl-like, or
|
||||
non-POSIX) will report `Samwise` as a match, but the standard Aho-Corasick
|
||||
algorithm modified for reporting non-overlapping matches will report `Sam`.
|
||||
|
||||
A novel contribution of this library is the ability to change the match
|
||||
semantics of Aho-Corasick (without additional search time overhead) such that
|
||||
`Samwise` is reported instead. For example, here's the standard approach:
|
||||
|
||||
```rust
|
||||
use aho_corasick::AhoCorasick;
|
||||
|
||||
let patterns = &["Samwise", "Sam"];
|
||||
let haystack = "Samwise";
|
||||
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
let mat = ac.find(haystack).expect("should have a match");
|
||||
assert_eq!("Sam", &haystack[mat.start()..mat.end()]);
|
||||
```
|
||||
|
||||
And now here's the leftmost-first version, which matches how a Perl-like
|
||||
regex will work:
|
||||
|
||||
```rust
|
||||
use aho_corasick::{AhoCorasickBuilder, MatchKind};
|
||||
|
||||
let patterns = &["Samwise", "Sam"];
|
||||
let haystack = "Samwise";
|
||||
|
||||
let ac = AhoCorasickBuilder::new()
|
||||
.match_kind(MatchKind::LeftmostFirst)
|
||||
.build(patterns);
|
||||
let mat = ac.find(haystack).expect("should have a match");
|
||||
assert_eq!("Samwise", &haystack[mat.start()..mat.end()]);
|
||||
```
|
||||
|
||||
In addition to leftmost-first semantics, this library also supports
|
||||
leftmost-longest semantics, which match the POSIX behavior of a regular
|
||||
expression alternation. See `MatchKind` in the docs for more details.
|
||||
|
||||
|
||||
### Minimum Rust version policy
|
||||
|
||||
This crate's minimum supported `rustc` version is `1.41.1`.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### FFI bindings
|
||||
|
||||
* [G-Research/ahocorasick_rs](https://github.com/G-Research/ahocorasick_rs/)
|
||||
is a Python wrapper for this library.
|
||||
|
||||
|
||||
### Future work
|
||||
|
||||
Here are some plans for the future:
|
||||
|
||||
* Assuming the current API is sufficient, I'd like to commit to it and release
|
||||
a `1.0` version of this crate some time in the next 6-12 months.
|
||||
* Support stream searching with leftmost match semantics. Currently, only
|
||||
standard match semantics are supported. Getting this right seems possible,
|
||||
but is tricky since the match state needs to be propagated through multiple
|
||||
searches. (With standard semantics, as soon as a match is seen the search
|
||||
ends.)
|
||||
24
clamav/libclamav_rust/.cargo/vendor/aho-corasick/UNLICENSE
vendored
Normal file
24
clamav/libclamav_rust/.cargo/vendor/aho-corasick/UNLICENSE
vendored
Normal file
@@ -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/>
|
||||
2
clamav/libclamav_rust/.cargo/vendor/aho-corasick/rustfmt.toml
vendored
Normal file
2
clamav/libclamav_rust/.cargo/vendor/aho-corasick/rustfmt.toml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
max_width = 79
|
||||
use_small_heuristics = "max"
|
||||
2141
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/ahocorasick.rs
vendored
Normal file
2141
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/ahocorasick.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
573
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/automaton.rs
vendored
Normal file
573
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/automaton.rs
vendored
Normal file
@@ -0,0 +1,573 @@
|
||||
use crate::ahocorasick::MatchKind;
|
||||
use crate::prefilter::{self, Candidate, Prefilter, PrefilterState};
|
||||
use crate::state_id::{dead_id, fail_id, StateID};
|
||||
use crate::Match;
|
||||
|
||||
// NOTE: This trait essentially started as a copy of the same trait from from
|
||||
// regex-automata, with some wording changed since we use this trait for
|
||||
// NFAs in addition to DFAs in this crate. Additionally, we do not export
|
||||
// this trait. It's only used internally to reduce code duplication. The
|
||||
// regex-automata crate needs to expose it because its Regex type is generic
|
||||
// over implementations of this trait. In this crate, we encapsulate everything
|
||||
// behind the AhoCorasick type.
|
||||
//
|
||||
// This trait is a bit of a mess, but it's not quite clear how to fix it.
|
||||
// Basically, there are several competing concerns:
|
||||
//
|
||||
// * We need performance, so everything effectively needs to get monomorphized.
|
||||
// * There are several variations on searching Aho-Corasick automatons:
|
||||
// overlapping, standard and leftmost. Overlapping and standard are somewhat
|
||||
// combined together below, but there is no real way to combine standard with
|
||||
// leftmost. Namely, leftmost requires continuing a search even after a match
|
||||
// is found, in order to correctly disambiguate a match.
|
||||
// * On top of that, *sometimes* callers want to know which state the automaton
|
||||
// is in after searching. This is principally useful for overlapping and
|
||||
// stream searches. However, when callers don't care about this, we really
|
||||
// do not want to be forced to compute it, since it sometimes requires extra
|
||||
// work. Thus, there are effectively two copies of leftmost searching: one
|
||||
// for tracking the state ID and one that doesn't. We should ideally do the
|
||||
// same for standard searching, but my sanity stopped me.
|
||||
|
||||
// SAFETY RATIONALE: Previously, the code below went to some length to remove
|
||||
// all bounds checks. This generally produced tighter assembly and lead to
|
||||
// 20-50% improvements in micro-benchmarks on corpora made up of random
|
||||
// characters. This somewhat makes sense, since the branch predictor is going
|
||||
// to be at its worse on random text.
|
||||
//
|
||||
// However, using the aho-corasick-debug tool and manually benchmarking
|
||||
// different inputs, the code *with* bounds checks actually wound up being
|
||||
// slightly faster:
|
||||
//
|
||||
// $ cat input
|
||||
// Sherlock Holmes
|
||||
// John Watson
|
||||
// Professor Moriarty
|
||||
// Irene Adler
|
||||
// Mary Watson
|
||||
//
|
||||
// $ aho-corasick-debug-safe \
|
||||
// input OpenSubtitles2018.raw.sample.en --kind leftmost-first --dfa
|
||||
// pattern read time: 32.824µs
|
||||
// automaton build time: 444.687µs
|
||||
// automaton heap usage: 72392 bytes
|
||||
// match count: 639
|
||||
// count time: 1.809961702s
|
||||
//
|
||||
// $ aho-corasick-debug-master \
|
||||
// input OpenSubtitles2018.raw.sample.en --kind leftmost-first --dfa
|
||||
// pattern read time: 31.425µs
|
||||
// automaton build time: 317.434µs
|
||||
// automaton heap usage: 72392 bytes
|
||||
// match count: 639
|
||||
// count time: 2.059157705s
|
||||
//
|
||||
// I was able to reproduce this result on two different machines (an i5 and
|
||||
// an i7). Therefore, we go the route of safe code for now.
|
||||
|
||||
/// A trait describing the interface of an Aho-Corasick finite state machine.
|
||||
///
|
||||
/// Every automaton has exactly one fail state, one dead state and exactly one
|
||||
/// start state. Generally, these correspond to the first, second and third
|
||||
/// states, respectively. The dead state is always treated as a sentinel. That
|
||||
/// is, no correct Aho-Corasick automaton will ever transition into the fail
|
||||
/// state. The dead state, however, can be transitioned into, but only when
|
||||
/// leftmost-first or leftmost-longest match semantics are enabled and only
|
||||
/// when at least one match has been observed.
|
||||
///
|
||||
/// Every automaton also has one or more match states, such that
|
||||
/// `Automaton::is_match_state(id)` returns `true` if and only if `id`
|
||||
/// corresponds to a match state.
|
||||
pub trait Automaton {
|
||||
/// The representation used for state identifiers in this automaton.
|
||||
///
|
||||
/// Typically, this is one of `u8`, `u16`, `u32`, `u64` or `usize`.
|
||||
type ID: StateID;
|
||||
|
||||
/// The type of matching that should be done.
|
||||
fn match_kind(&self) -> &MatchKind;
|
||||
|
||||
/// Returns true if and only if this automaton uses anchored searches.
|
||||
fn anchored(&self) -> bool;
|
||||
|
||||
/// An optional prefilter for quickly skipping to the next candidate match.
|
||||
/// A prefilter must report at least every match, although it may report
|
||||
/// positions that do not correspond to a match. That is, it must not allow
|
||||
/// false negatives, but can allow false positives.
|
||||
///
|
||||
/// Currently, a prefilter only runs when the automaton is in the start
|
||||
/// state. That is, the position reported by a prefilter should always
|
||||
/// correspond to the start of a potential match.
|
||||
fn prefilter(&self) -> Option<&dyn Prefilter>;
|
||||
|
||||
/// Return the identifier of this automaton's start state.
|
||||
fn start_state(&self) -> Self::ID;
|
||||
|
||||
/// Returns true if and only if the given state identifier refers to a
|
||||
/// valid state.
|
||||
fn is_valid(&self, id: Self::ID) -> bool;
|
||||
|
||||
/// Returns true if and only if the given identifier corresponds to a match
|
||||
/// state.
|
||||
///
|
||||
/// The state ID given must be valid, or else implementors may panic.
|
||||
fn is_match_state(&self, id: Self::ID) -> bool;
|
||||
|
||||
/// Returns true if and only if the given identifier corresponds to a state
|
||||
/// that is either the dead state or a match state.
|
||||
///
|
||||
/// Depending on the implementation of the automaton, this routine can
|
||||
/// be used to save a branch in the core matching loop. Nevertheless,
|
||||
/// `is_match_state(id) || id == dead_id()` is always a valid
|
||||
/// implementation. Indeed, this is the default implementation.
|
||||
///
|
||||
/// The state ID given must be valid, or else implementors may panic.
|
||||
fn is_match_or_dead_state(&self, id: Self::ID) -> bool {
|
||||
id == dead_id() || self.is_match_state(id)
|
||||
}
|
||||
|
||||
/// If the given state is a match state, return the match corresponding
|
||||
/// to the given match index. `end` must be the ending position of the
|
||||
/// detected match. If no match exists or if `match_index` exceeds the
|
||||
/// number of matches in this state, then `None` is returned.
|
||||
///
|
||||
/// The state ID given must be valid, or else implementors may panic.
|
||||
///
|
||||
/// If the given state ID is correct and if the `match_index` is less than
|
||||
/// the number of matches for that state, then this is guaranteed to return
|
||||
/// a match.
|
||||
fn get_match(
|
||||
&self,
|
||||
id: Self::ID,
|
||||
match_index: usize,
|
||||
end: usize,
|
||||
) -> Option<Match>;
|
||||
|
||||
/// Returns the number of matches for the given state. If the given state
|
||||
/// is not a match state, then this returns 0.
|
||||
///
|
||||
/// The state ID given must be valid, or else implementors must panic.
|
||||
fn match_count(&self, id: Self::ID) -> usize;
|
||||
|
||||
/// Given the current state that this automaton is in and the next input
|
||||
/// byte, this method returns the identifier of the next state. The
|
||||
/// identifier returned must always be valid and may never correspond to
|
||||
/// the fail state. The returned identifier may, however, point to the
|
||||
/// dead state.
|
||||
///
|
||||
/// This is not safe so that implementors may look up the next state
|
||||
/// without memory safety checks such as bounds checks. As such, callers
|
||||
/// must ensure that the given identifier corresponds to a valid automaton
|
||||
/// state. Implementors must, in turn, ensure that this routine is safe for
|
||||
/// all valid state identifiers and for all possible `u8` values.
|
||||
fn next_state(&self, current: Self::ID, input: u8) -> Self::ID;
|
||||
|
||||
/// Like next_state, but debug_asserts that the underlying
|
||||
/// implementation never returns a `fail_id()` for the next state.
|
||||
fn next_state_no_fail(&self, current: Self::ID, input: u8) -> Self::ID {
|
||||
let next = self.next_state(current, input);
|
||||
// We should never see a transition to the failure state.
|
||||
debug_assert!(
|
||||
next != fail_id(),
|
||||
"automaton should never return fail_id for next state"
|
||||
);
|
||||
next
|
||||
}
|
||||
|
||||
/// Execute a search using standard match semantics.
|
||||
///
|
||||
/// This can be used even when the automaton was constructed with leftmost
|
||||
/// match semantics when you want to find the earliest possible match. This
|
||||
/// can also be used as part of an overlapping search implementation.
|
||||
///
|
||||
/// N.B. This does not report a match if `state_id` is given as a matching
|
||||
/// state. As such, this should not be used directly.
|
||||
#[inline(always)]
|
||||
fn standard_find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
) -> Option<Match> {
|
||||
if let Some(pre) = self.prefilter() {
|
||||
self.standard_find_at_imp(
|
||||
prestate,
|
||||
Some(pre),
|
||||
haystack,
|
||||
at,
|
||||
state_id,
|
||||
)
|
||||
} else {
|
||||
self.standard_find_at_imp(prestate, None, haystack, at, state_id)
|
||||
}
|
||||
}
|
||||
|
||||
// It's important for this to always be inlined. Namely, its only caller
|
||||
// is standard_find_at, and the inlining should remove the case analysis
|
||||
// for prefilter scanning when there is no prefilter available.
|
||||
#[inline(always)]
|
||||
fn standard_find_at_imp(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
prefilter: Option<&dyn Prefilter>,
|
||||
haystack: &[u8],
|
||||
mut at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
) -> Option<Match> {
|
||||
while at < haystack.len() {
|
||||
if let Some(pre) = prefilter {
|
||||
if prestate.is_effective(at) && *state_id == self.start_state()
|
||||
{
|
||||
let c = prefilter::next(prestate, pre, haystack, at)
|
||||
.into_option();
|
||||
match c {
|
||||
None => return None,
|
||||
Some(i) => {
|
||||
at = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// CORRECTNESS: next_state is correct for all possible u8 values,
|
||||
// so the only thing we're concerned about is the validity of
|
||||
// `state_id`. `state_id` either comes from the caller (in which
|
||||
// case, we assume it is correct), or it comes from the return
|
||||
// value of next_state, which is guaranteed to be correct.
|
||||
*state_id = self.next_state_no_fail(*state_id, haystack[at]);
|
||||
at += 1;
|
||||
// This routine always quits immediately after seeing a
|
||||
// match, and since dead states can only come after seeing
|
||||
// a match, seeing a dead state here is impossible. (Unless
|
||||
// we have an anchored automaton, in which case, dead states
|
||||
// are used to stop a search.)
|
||||
debug_assert!(
|
||||
*state_id != dead_id() || self.anchored(),
|
||||
"standard find should never see a dead state"
|
||||
);
|
||||
|
||||
if self.is_match_or_dead_state(*state_id) {
|
||||
return if *state_id == dead_id() {
|
||||
None
|
||||
} else {
|
||||
self.get_match(*state_id, 0, at)
|
||||
};
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Execute a search using leftmost (either first or longest) match
|
||||
/// semantics.
|
||||
///
|
||||
/// The principle difference between searching with standard semantics and
|
||||
/// searching with leftmost semantics is that leftmost searching will
|
||||
/// continue searching even after a match has been found. Once a match
|
||||
/// is found, the search does not stop until either the haystack has been
|
||||
/// exhausted or a dead state is observed in the automaton. (Dead states
|
||||
/// only exist in automatons constructed with leftmost semantics.) That is,
|
||||
/// we rely on the construction of the automaton to tell us when to quit.
|
||||
#[inline(never)]
|
||||
fn leftmost_find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
) -> Option<Match> {
|
||||
if let Some(pre) = self.prefilter() {
|
||||
self.leftmost_find_at_imp(
|
||||
prestate,
|
||||
Some(pre),
|
||||
haystack,
|
||||
at,
|
||||
state_id,
|
||||
)
|
||||
} else {
|
||||
self.leftmost_find_at_imp(prestate, None, haystack, at, state_id)
|
||||
}
|
||||
}
|
||||
|
||||
// It's important for this to always be inlined. Namely, its only caller
|
||||
// is leftmost_find_at, and the inlining should remove the case analysis
|
||||
// for prefilter scanning when there is no prefilter available.
|
||||
#[inline(always)]
|
||||
fn leftmost_find_at_imp(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
prefilter: Option<&dyn Prefilter>,
|
||||
haystack: &[u8],
|
||||
mut at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
) -> Option<Match> {
|
||||
debug_assert!(self.match_kind().is_leftmost());
|
||||
if self.anchored() && at > 0 && *state_id == self.start_state() {
|
||||
return None;
|
||||
}
|
||||
let mut last_match = self.get_match(*state_id, 0, at);
|
||||
while at < haystack.len() {
|
||||
if let Some(pre) = prefilter {
|
||||
if prestate.is_effective(at) && *state_id == self.start_state()
|
||||
{
|
||||
let c = prefilter::next(prestate, pre, haystack, at)
|
||||
.into_option();
|
||||
match c {
|
||||
None => return None,
|
||||
Some(i) => {
|
||||
at = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// CORRECTNESS: next_state is correct for all possible u8 values,
|
||||
// so the only thing we're concerned about is the validity of
|
||||
// `state_id`. `state_id` either comes from the caller (in which
|
||||
// case, we assume it is correct), or it comes from the return
|
||||
// value of next_state, which is guaranteed to be correct.
|
||||
*state_id = self.next_state_no_fail(*state_id, haystack[at]);
|
||||
at += 1;
|
||||
if self.is_match_or_dead_state(*state_id) {
|
||||
if *state_id == dead_id() {
|
||||
// The only way to enter into a dead state is if a match
|
||||
// has been found, so we assert as much. This is different
|
||||
// from normal automata, where you might enter a dead state
|
||||
// if you know a subsequent match will never be found
|
||||
// (regardless of whether a match has already been found).
|
||||
// For Aho-Corasick, it is built so that we can match at
|
||||
// any position, so the possibility of a match always
|
||||
// exists.
|
||||
//
|
||||
// (Unless we have an anchored automaton, in which case,
|
||||
// dead states are used to stop a search.)
|
||||
debug_assert!(
|
||||
last_match.is_some() || self.anchored(),
|
||||
"dead state should only be seen after match"
|
||||
);
|
||||
return last_match;
|
||||
}
|
||||
last_match = self.get_match(*state_id, 0, at);
|
||||
}
|
||||
}
|
||||
last_match
|
||||
}
|
||||
|
||||
/// This is like leftmost_find_at, but does not need to track a caller
|
||||
/// provided state id. In other words, the only output of this routine is a
|
||||
/// match, if one exists.
|
||||
///
|
||||
/// It is regrettable that we need to effectively copy a chunk of
|
||||
/// implementation twice, but when we don't need to track the state ID, we
|
||||
/// can allow the prefilter to report matches immediately without having
|
||||
/// to re-confirm them with the automaton. The re-confirmation step is
|
||||
/// necessary in leftmost_find_at because tracing through the automaton is
|
||||
/// the only way to correctly set the state ID. (Perhaps an alternative
|
||||
/// would be to keep a map from pattern ID to matching state ID, but that
|
||||
/// complicates the code and still doesn't permit us to defer to the
|
||||
/// prefilter entirely when possible.)
|
||||
///
|
||||
/// I did try a few things to avoid the code duplication here, but nothing
|
||||
/// optimized as well as this approach. (In microbenchmarks, there was
|
||||
/// about a 25% difference.)
|
||||
#[inline(never)]
|
||||
fn leftmost_find_at_no_state(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
) -> Option<Match> {
|
||||
if let Some(pre) = self.prefilter() {
|
||||
self.leftmost_find_at_no_state_imp(
|
||||
prestate,
|
||||
Some(pre),
|
||||
haystack,
|
||||
at,
|
||||
)
|
||||
} else {
|
||||
self.leftmost_find_at_no_state_imp(prestate, None, haystack, at)
|
||||
}
|
||||
}
|
||||
|
||||
// It's important for this to always be inlined. Namely, its only caller
|
||||
// is leftmost_find_at_no_state, and the inlining should remove the case
|
||||
// analysis for prefilter scanning when there is no prefilter available.
|
||||
#[inline(always)]
|
||||
fn leftmost_find_at_no_state_imp(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
prefilter: Option<&dyn Prefilter>,
|
||||
haystack: &[u8],
|
||||
mut at: usize,
|
||||
) -> Option<Match> {
|
||||
debug_assert!(self.match_kind().is_leftmost());
|
||||
if self.anchored() && at > 0 {
|
||||
return None;
|
||||
}
|
||||
// If our prefilter handles confirmation of matches 100% of the
|
||||
// time, and since we don't need to track state IDs, we can avoid
|
||||
// Aho-Corasick completely.
|
||||
if let Some(pre) = prefilter {
|
||||
// We should never have a prefilter during an anchored search.
|
||||
debug_assert!(!self.anchored());
|
||||
if !pre.reports_false_positives() {
|
||||
return match pre.next_candidate(prestate, haystack, at) {
|
||||
Candidate::None => None,
|
||||
Candidate::Match(m) => Some(m),
|
||||
Candidate::PossibleStartOfMatch(_) => unreachable!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let mut state_id = self.start_state();
|
||||
let mut last_match = self.get_match(state_id, 0, at);
|
||||
while at < haystack.len() {
|
||||
if let Some(pre) = prefilter {
|
||||
if prestate.is_effective(at) && state_id == self.start_state()
|
||||
{
|
||||
match prefilter::next(prestate, pre, haystack, at) {
|
||||
Candidate::None => return None,
|
||||
// Since we aren't tracking a state ID, we can
|
||||
// quit early once we know we have a match.
|
||||
Candidate::Match(m) => return Some(m),
|
||||
Candidate::PossibleStartOfMatch(i) => {
|
||||
at = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// CORRECTNESS: next_state is correct for all possible u8 values,
|
||||
// so the only thing we're concerned about is the validity of
|
||||
// `state_id`. `state_id` either comes from the caller (in which
|
||||
// case, we assume it is correct), or it comes from the return
|
||||
// value of next_state, which is guaranteed to be correct.
|
||||
state_id = self.next_state_no_fail(state_id, haystack[at]);
|
||||
at += 1;
|
||||
if self.is_match_or_dead_state(state_id) {
|
||||
if state_id == dead_id() {
|
||||
// The only way to enter into a dead state is if a
|
||||
// match has been found, so we assert as much. This
|
||||
// is different from normal automata, where you might
|
||||
// enter a dead state if you know a subsequent match
|
||||
// will never be found (regardless of whether a match
|
||||
// has already been found). For Aho-Corasick, it is
|
||||
// built so that we can match at any position, so the
|
||||
// possibility of a match always exists.
|
||||
//
|
||||
// (Unless we have an anchored automaton, in which
|
||||
// case, dead states are used to stop a search.)
|
||||
debug_assert!(
|
||||
last_match.is_some() || self.anchored(),
|
||||
"dead state should only be seen after match"
|
||||
);
|
||||
return last_match;
|
||||
}
|
||||
last_match = self.get_match(state_id, 0, at);
|
||||
}
|
||||
}
|
||||
last_match
|
||||
}
|
||||
|
||||
/// Execute an overlapping search.
|
||||
///
|
||||
/// When executing an overlapping match, the previous state ID in addition
|
||||
/// to the previous match index should be given. If there are more matches
|
||||
/// at the given state, then the match is reported and the given index is
|
||||
/// incremented.
|
||||
#[inline(always)]
|
||||
fn overlapping_find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
match_index: &mut usize,
|
||||
) -> Option<Match> {
|
||||
if self.anchored() && at > 0 && *state_id == self.start_state() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let match_count = self.match_count(*state_id);
|
||||
if *match_index < match_count {
|
||||
// This is guaranteed to return a match since
|
||||
// match_index < match_count.
|
||||
let result = self.get_match(*state_id, *match_index, at);
|
||||
debug_assert!(result.is_some(), "must be a match");
|
||||
*match_index += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
*match_index = 0;
|
||||
match self.standard_find_at(prestate, haystack, at, state_id) {
|
||||
None => None,
|
||||
Some(m) => {
|
||||
*match_index = 1;
|
||||
Some(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the earliest match found. This returns as soon as we know that
|
||||
/// we have a match. As such, this does not necessarily correspond to the
|
||||
/// leftmost starting match, but rather, the leftmost position at which a
|
||||
/// match ends.
|
||||
#[inline(always)]
|
||||
fn earliest_find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
) -> Option<Match> {
|
||||
if *state_id == self.start_state() {
|
||||
if self.anchored() && at > 0 {
|
||||
return None;
|
||||
}
|
||||
if let Some(m) = self.get_match(*state_id, 0, at) {
|
||||
return Some(m);
|
||||
}
|
||||
}
|
||||
self.standard_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
|
||||
/// A convenience function for finding the next match according to the
|
||||
/// match semantics of this automaton. For standard match semantics, this
|
||||
/// finds the earliest match. Otherwise, the leftmost match is found.
|
||||
#[inline(always)]
|
||||
fn find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut Self::ID,
|
||||
) -> Option<Match> {
|
||||
match *self.match_kind() {
|
||||
MatchKind::Standard => {
|
||||
self.earliest_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
MatchKind::LeftmostFirst | MatchKind::LeftmostLongest => {
|
||||
self.leftmost_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
MatchKind::__Nonexhaustive => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Like find_at, but does not track state identifiers. This permits some
|
||||
/// optimizations when a prefilter that confirms its own matches is
|
||||
/// present.
|
||||
#[inline(always)]
|
||||
fn find_at_no_state(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
) -> Option<Match> {
|
||||
match *self.match_kind() {
|
||||
MatchKind::Standard => {
|
||||
let mut state = self.start_state();
|
||||
self.earliest_find_at(prestate, haystack, at, &mut state)
|
||||
}
|
||||
MatchKind::LeftmostFirst | MatchKind::LeftmostLongest => {
|
||||
self.leftmost_find_at_no_state(prestate, haystack, at)
|
||||
}
|
||||
MatchKind::__Nonexhaustive => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
132
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/buffer.rs
vendored
Normal file
132
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/buffer.rs
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::ptr;
|
||||
|
||||
/// The default buffer capacity that we use for the stream buffer.
|
||||
const DEFAULT_BUFFER_CAPACITY: usize = 8 * (1 << 10); // 8 KB
|
||||
|
||||
/// A fairly simple roll buffer for supporting stream searches.
|
||||
///
|
||||
/// This buffer acts as a temporary place to store a fixed amount of data when
|
||||
/// reading from a stream. Its central purpose is to allow "rolling" some
|
||||
/// suffix of the data to the beginning of the buffer before refilling it with
|
||||
/// more data from the stream. For example, let's say we are trying to match
|
||||
/// "foobar" on a stream. When we report the match, we'd like to not only
|
||||
/// report the correct offsets at which the match occurs, but also the matching
|
||||
/// bytes themselves. So let's say our stream is a file with the following
|
||||
/// contents: `test test foobar test test`. Now assume that we happen to read
|
||||
/// the aforementioned file in two chunks: `test test foo` and `bar test test`.
|
||||
/// Naively, it would not be possible to report a single contiguous `foobar`
|
||||
/// match, but this roll buffer allows us to do that. Namely, after the second
|
||||
/// read, the contents of the buffer should be `st foobar test test`, where the
|
||||
/// search should ultimately resume immediately after `foo`. (The prefix `st `
|
||||
/// is included because the roll buffer saves N bytes at the end of the buffer,
|
||||
/// where N is the maximum possible length of a match.)
|
||||
///
|
||||
/// A lot of the logic for dealing with this is unfortunately split out between
|
||||
/// this roll buffer and the `StreamChunkIter`.
|
||||
#[derive(Debug)]
|
||||
pub struct Buffer {
|
||||
/// The raw buffer contents. This has a fixed size and never increases.
|
||||
buf: Vec<u8>,
|
||||
/// The minimum size of the buffer, which is equivalent to the maximum
|
||||
/// possible length of a match. This corresponds to the amount that we
|
||||
/// roll
|
||||
min: usize,
|
||||
/// The end of the contents of this buffer.
|
||||
end: usize,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
/// Create a new buffer for stream searching. The minimum buffer length
|
||||
/// given should be the size of the maximum possible match length.
|
||||
pub fn new(min_buffer_len: usize) -> Buffer {
|
||||
let min = cmp::max(1, min_buffer_len);
|
||||
// The minimum buffer amount is also the amount that we roll our
|
||||
// buffer in order to support incremental searching. To this end,
|
||||
// our actual capacity needs to be at least 1 byte bigger than our
|
||||
// minimum amount, otherwise we won't have any overlap. In actuality,
|
||||
// we want our buffer to be a bit bigger than that for performance
|
||||
// reasons, so we set a lower bound of `8 * min`.
|
||||
//
|
||||
// TODO: It would be good to find a way to test the streaming
|
||||
// implementation with the minimal buffer size. For now, we just
|
||||
// uncomment out the next line and comment out the subsequent line.
|
||||
// let capacity = 1 + min;
|
||||
let capacity = cmp::max(min * 8, DEFAULT_BUFFER_CAPACITY);
|
||||
Buffer { buf: vec![0; capacity], min, end: 0 }
|
||||
}
|
||||
|
||||
/// Return the contents of this buffer.
|
||||
#[inline]
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buf[..self.end]
|
||||
}
|
||||
|
||||
/// Return the minimum size of the buffer. The only way a buffer may be
|
||||
/// smaller than this is if the stream itself contains less than the
|
||||
/// minimum buffer amount.
|
||||
#[inline]
|
||||
pub fn min_buffer_len(&self) -> usize {
|
||||
self.min
|
||||
}
|
||||
|
||||
/// Return the total length of the contents in the buffer.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.end
|
||||
}
|
||||
|
||||
/// Return all free capacity in this buffer.
|
||||
fn free_buffer(&mut self) -> &mut [u8] {
|
||||
&mut self.buf[self.end..]
|
||||
}
|
||||
|
||||
/// Refill the contents of this buffer by reading as much as possible into
|
||||
/// this buffer's free capacity. If no more bytes could be read, then this
|
||||
/// returns false. Otherwise, this reads until it has filled the buffer
|
||||
/// past the minimum amount.
|
||||
pub fn fill<R: io::Read>(&mut self, mut rdr: R) -> io::Result<bool> {
|
||||
let mut readany = false;
|
||||
loop {
|
||||
let readlen = rdr.read(self.free_buffer())?;
|
||||
if readlen == 0 {
|
||||
return Ok(readany);
|
||||
}
|
||||
readany = true;
|
||||
self.end += readlen;
|
||||
if self.len() >= self.min {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Roll the contents of the buffer so that the suffix of this buffer is
|
||||
/// moved to the front and all other contents are dropped. The size of the
|
||||
/// suffix corresponds precisely to the minimum buffer length.
|
||||
///
|
||||
/// This should only be called when the entire contents of this buffer have
|
||||
/// been searched.
|
||||
pub fn roll(&mut self) {
|
||||
let roll_start = self
|
||||
.end
|
||||
.checked_sub(self.min)
|
||||
.expect("buffer capacity should be bigger than minimum amount");
|
||||
let roll_len = self.min;
|
||||
|
||||
assert!(roll_start + roll_len <= self.end);
|
||||
unsafe {
|
||||
// SAFETY: A buffer contains Copy data, so there's no problem
|
||||
// moving it around. Safety also depends on our indices being in
|
||||
// bounds, which they always should be, given the assert above.
|
||||
//
|
||||
// TODO: Switch to [T]::copy_within once our MSRV is high enough.
|
||||
ptr::copy(
|
||||
self.buf[roll_start..].as_ptr(),
|
||||
self.buf.as_mut_ptr(),
|
||||
roll_len,
|
||||
);
|
||||
}
|
||||
self.end = roll_len;
|
||||
}
|
||||
}
|
||||
258
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/byte_frequencies.rs
vendored
Normal file
258
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/byte_frequencies.rs
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
pub const BYTE_FREQUENCIES: [u8; 256] = [
|
||||
55, // '\x00'
|
||||
52, // '\x01'
|
||||
51, // '\x02'
|
||||
50, // '\x03'
|
||||
49, // '\x04'
|
||||
48, // '\x05'
|
||||
47, // '\x06'
|
||||
46, // '\x07'
|
||||
45, // '\x08'
|
||||
103, // '\t'
|
||||
242, // '\n'
|
||||
66, // '\x0b'
|
||||
67, // '\x0c'
|
||||
229, // '\r'
|
||||
44, // '\x0e'
|
||||
43, // '\x0f'
|
||||
42, // '\x10'
|
||||
41, // '\x11'
|
||||
40, // '\x12'
|
||||
39, // '\x13'
|
||||
38, // '\x14'
|
||||
37, // '\x15'
|
||||
36, // '\x16'
|
||||
35, // '\x17'
|
||||
34, // '\x18'
|
||||
33, // '\x19'
|
||||
56, // '\x1a'
|
||||
32, // '\x1b'
|
||||
31, // '\x1c'
|
||||
30, // '\x1d'
|
||||
29, // '\x1e'
|
||||
28, // '\x1f'
|
||||
255, // ' '
|
||||
148, // '!'
|
||||
164, // '"'
|
||||
149, // '#'
|
||||
136, // '$'
|
||||
160, // '%'
|
||||
155, // '&'
|
||||
173, // "'"
|
||||
221, // '('
|
||||
222, // ')'
|
||||
134, // '*'
|
||||
122, // '+'
|
||||
232, // ','
|
||||
202, // '-'
|
||||
215, // '.'
|
||||
224, // '/'
|
||||
208, // '0'
|
||||
220, // '1'
|
||||
204, // '2'
|
||||
187, // '3'
|
||||
183, // '4'
|
||||
179, // '5'
|
||||
177, // '6'
|
||||
168, // '7'
|
||||
178, // '8'
|
||||
200, // '9'
|
||||
226, // ':'
|
||||
195, // ';'
|
||||
154, // '<'
|
||||
184, // '='
|
||||
174, // '>'
|
||||
126, // '?'
|
||||
120, // '@'
|
||||
191, // 'A'
|
||||
157, // 'B'
|
||||
194, // 'C'
|
||||
170, // 'D'
|
||||
189, // 'E'
|
||||
162, // 'F'
|
||||
161, // 'G'
|
||||
150, // 'H'
|
||||
193, // 'I'
|
||||
142, // 'J'
|
||||
137, // 'K'
|
||||
171, // 'L'
|
||||
176, // 'M'
|
||||
185, // 'N'
|
||||
167, // 'O'
|
||||
186, // 'P'
|
||||
112, // 'Q'
|
||||
175, // 'R'
|
||||
192, // 'S'
|
||||
188, // 'T'
|
||||
156, // 'U'
|
||||
140, // 'V'
|
||||
143, // 'W'
|
||||
123, // 'X'
|
||||
133, // 'Y'
|
||||
128, // 'Z'
|
||||
147, // '['
|
||||
138, // '\\'
|
||||
146, // ']'
|
||||
114, // '^'
|
||||
223, // '_'
|
||||
151, // '`'
|
||||
249, // 'a'
|
||||
216, // 'b'
|
||||
238, // 'c'
|
||||
236, // 'd'
|
||||
253, // 'e'
|
||||
227, // 'f'
|
||||
218, // 'g'
|
||||
230, // 'h'
|
||||
247, // 'i'
|
||||
135, // 'j'
|
||||
180, // 'k'
|
||||
241, // 'l'
|
||||
233, // 'm'
|
||||
246, // 'n'
|
||||
244, // 'o'
|
||||
231, // 'p'
|
||||
139, // 'q'
|
||||
245, // 'r'
|
||||
243, // 's'
|
||||
251, // 't'
|
||||
235, // 'u'
|
||||
201, // 'v'
|
||||
196, // 'w'
|
||||
240, // 'x'
|
||||
214, // 'y'
|
||||
152, // 'z'
|
||||
182, // '{'
|
||||
205, // '|'
|
||||
181, // '}'
|
||||
127, // '~'
|
||||
27, // '\x7f'
|
||||
212, // '\x80'
|
||||
211, // '\x81'
|
||||
210, // '\x82'
|
||||
213, // '\x83'
|
||||
228, // '\x84'
|
||||
197, // '\x85'
|
||||
169, // '\x86'
|
||||
159, // '\x87'
|
||||
131, // '\x88'
|
||||
172, // '\x89'
|
||||
105, // '\x8a'
|
||||
80, // '\x8b'
|
||||
98, // '\x8c'
|
||||
96, // '\x8d'
|
||||
97, // '\x8e'
|
||||
81, // '\x8f'
|
||||
207, // '\x90'
|
||||
145, // '\x91'
|
||||
116, // '\x92'
|
||||
115, // '\x93'
|
||||
144, // '\x94'
|
||||
130, // '\x95'
|
||||
153, // '\x96'
|
||||
121, // '\x97'
|
||||
107, // '\x98'
|
||||
132, // '\x99'
|
||||
109, // '\x9a'
|
||||
110, // '\x9b'
|
||||
124, // '\x9c'
|
||||
111, // '\x9d'
|
||||
82, // '\x9e'
|
||||
108, // '\x9f'
|
||||
118, // '\xa0'
|
||||
141, // '¡'
|
||||
113, // '¢'
|
||||
129, // '£'
|
||||
119, // '¤'
|
||||
125, // '¥'
|
||||
165, // '¦'
|
||||
117, // '§'
|
||||
92, // '¨'
|
||||
106, // '©'
|
||||
83, // 'ª'
|
||||
72, // '«'
|
||||
99, // '¬'
|
||||
93, // '\xad'
|
||||
65, // '®'
|
||||
79, // '¯'
|
||||
166, // '°'
|
||||
237, // '±'
|
||||
163, // '²'
|
||||
199, // '³'
|
||||
190, // '´'
|
||||
225, // 'µ'
|
||||
209, // '¶'
|
||||
203, // '·'
|
||||
198, // '¸'
|
||||
217, // '¹'
|
||||
219, // 'º'
|
||||
206, // '»'
|
||||
234, // '¼'
|
||||
248, // '½'
|
||||
158, // '¾'
|
||||
239, // '¿'
|
||||
255, // 'À'
|
||||
255, // 'Á'
|
||||
255, // 'Â'
|
||||
255, // 'Ã'
|
||||
255, // 'Ä'
|
||||
255, // 'Å'
|
||||
255, // 'Æ'
|
||||
255, // 'Ç'
|
||||
255, // 'È'
|
||||
255, // 'É'
|
||||
255, // 'Ê'
|
||||
255, // 'Ë'
|
||||
255, // 'Ì'
|
||||
255, // 'Í'
|
||||
255, // 'Î'
|
||||
255, // 'Ï'
|
||||
255, // 'Ð'
|
||||
255, // 'Ñ'
|
||||
255, // 'Ò'
|
||||
255, // 'Ó'
|
||||
255, // 'Ô'
|
||||
255, // 'Õ'
|
||||
255, // 'Ö'
|
||||
255, // '×'
|
||||
255, // 'Ø'
|
||||
255, // 'Ù'
|
||||
255, // 'Ú'
|
||||
255, // 'Û'
|
||||
255, // 'Ü'
|
||||
255, // 'Ý'
|
||||
255, // 'Þ'
|
||||
255, // 'ß'
|
||||
255, // 'à'
|
||||
255, // 'á'
|
||||
255, // 'â'
|
||||
255, // 'ã'
|
||||
255, // 'ä'
|
||||
255, // 'å'
|
||||
255, // 'æ'
|
||||
255, // 'ç'
|
||||
255, // 'è'
|
||||
255, // 'é'
|
||||
255, // 'ê'
|
||||
255, // 'ë'
|
||||
255, // 'ì'
|
||||
255, // 'í'
|
||||
255, // 'î'
|
||||
255, // 'ï'
|
||||
255, // 'ð'
|
||||
255, // 'ñ'
|
||||
255, // 'ò'
|
||||
255, // 'ó'
|
||||
255, // 'ô'
|
||||
255, // 'õ'
|
||||
255, // 'ö'
|
||||
255, // '÷'
|
||||
255, // 'ø'
|
||||
255, // 'ù'
|
||||
255, // 'ú'
|
||||
255, // 'û'
|
||||
255, // 'ü'
|
||||
255, // 'ý'
|
||||
255, // 'þ'
|
||||
255, // 'ÿ'
|
||||
];
|
||||
238
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/classes.rs
vendored
Normal file
238
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/classes.rs
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
use std::fmt;
|
||||
|
||||
/// A representation of byte oriented equivalence classes.
|
||||
///
|
||||
/// This is used in an FSM to reduce the size of the transition table. This can
|
||||
/// have a particularly large impact not only on the total size of an FSM, but
|
||||
/// also on compile times.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ByteClasses([u8; 256]);
|
||||
|
||||
impl ByteClasses {
|
||||
/// Creates a new set of equivalence classes where all bytes are mapped to
|
||||
/// the same class.
|
||||
pub fn empty() -> ByteClasses {
|
||||
ByteClasses([0; 256])
|
||||
}
|
||||
|
||||
/// Creates a new set of equivalence classes where each byte belongs to
|
||||
/// its own equivalence class.
|
||||
pub fn singletons() -> ByteClasses {
|
||||
let mut classes = ByteClasses::empty();
|
||||
for i in 0..256 {
|
||||
classes.set(i as u8, i as u8);
|
||||
}
|
||||
classes
|
||||
}
|
||||
|
||||
/// Set the equivalence class for the given byte.
|
||||
#[inline]
|
||||
pub fn set(&mut self, byte: u8, class: u8) {
|
||||
self.0[byte as usize] = class;
|
||||
}
|
||||
|
||||
/// Get the equivalence class for the given byte.
|
||||
#[inline]
|
||||
pub fn get(&self, byte: u8) -> u8 {
|
||||
// SAFETY: This is safe because all dense transitions have
|
||||
// exactly 256 elements, so all u8 values are valid indices.
|
||||
self.0[byte as usize]
|
||||
}
|
||||
|
||||
/// Return the total number of elements in the alphabet represented by
|
||||
/// these equivalence classes. Equivalently, this returns the total number
|
||||
/// of equivalence classes.
|
||||
#[inline]
|
||||
pub fn alphabet_len(&self) -> usize {
|
||||
self.0[255] as usize + 1
|
||||
}
|
||||
|
||||
/// Returns true if and only if every byte in this class maps to its own
|
||||
/// equivalence class. Equivalently, there are 256 equivalence classes
|
||||
/// and each class contains exactly one byte.
|
||||
#[inline]
|
||||
pub fn is_singleton(&self) -> bool {
|
||||
self.alphabet_len() == 256
|
||||
}
|
||||
|
||||
/// Returns an iterator over a sequence of representative bytes from each
|
||||
/// equivalence class. Namely, this yields exactly N items, where N is
|
||||
/// equivalent to the number of equivalence classes. Each item is an
|
||||
/// arbitrary byte drawn from each equivalence class.
|
||||
///
|
||||
/// This is useful when one is determinizing an NFA and the NFA's alphabet
|
||||
/// hasn't been converted to equivalence classes yet. Picking an arbitrary
|
||||
/// byte from each equivalence class then permits a full exploration of
|
||||
/// the NFA instead of using every possible byte value.
|
||||
pub fn representatives(&self) -> ByteClassRepresentatives<'_> {
|
||||
ByteClassRepresentatives { classes: self, byte: 0, last_class: None }
|
||||
}
|
||||
|
||||
/// Returns all of the bytes in the given equivalence class.
|
||||
///
|
||||
/// The second element in the tuple indicates the number of elements in
|
||||
/// the array.
|
||||
fn elements(&self, equiv: u8) -> ([u8; 256], usize) {
|
||||
let (mut array, mut len) = ([0; 256], 0);
|
||||
for b in 0..256 {
|
||||
if self.get(b as u8) == equiv {
|
||||
array[len] = b as u8;
|
||||
len += 1;
|
||||
}
|
||||
}
|
||||
(array, len)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ByteClasses {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.is_singleton() {
|
||||
write!(f, "ByteClasses({{singletons}})")
|
||||
} else {
|
||||
write!(f, "ByteClasses(")?;
|
||||
for equiv in 0..self.alphabet_len() {
|
||||
let (members, len) = self.elements(equiv as u8);
|
||||
write!(f, " {} => {:?}", equiv, &members[..len])?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over representative bytes from each equivalence class.
|
||||
#[derive(Debug)]
|
||||
pub struct ByteClassRepresentatives<'a> {
|
||||
classes: &'a ByteClasses,
|
||||
byte: usize,
|
||||
last_class: Option<u8>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ByteClassRepresentatives<'a> {
|
||||
type Item = u8;
|
||||
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
while self.byte < 256 {
|
||||
let byte = self.byte as u8;
|
||||
let class = self.classes.get(byte);
|
||||
self.byte += 1;
|
||||
|
||||
if self.last_class != Some(class) {
|
||||
self.last_class = Some(class);
|
||||
return Some(byte);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// A byte class builder keeps track of an *approximation* of equivalence
|
||||
/// classes of bytes during NFA construction. That is, every byte in an
|
||||
/// equivalence class cannot discriminate between a match and a non-match.
|
||||
///
|
||||
/// For example, in the literals `abc` and `xyz`, the bytes [\x00-`], [d-w]
|
||||
/// and [{-\xFF] never discriminate between a match and a non-match, precisely
|
||||
/// because they never occur in the literals anywhere.
|
||||
///
|
||||
/// Note though that this does not necessarily compute the minimal set of
|
||||
/// equivalence classes. For example, in the literals above, the byte ranges
|
||||
/// [\x00-`], [d-w] and [{-\xFF] are all treated as distinct equivalence
|
||||
/// classes even though they could be treated a single class. The reason for
|
||||
/// this is implementation complexity. In the future, we should endeavor to
|
||||
/// compute the minimal equivalence classes since they can have a rather large
|
||||
/// impact on the size of the DFA.
|
||||
///
|
||||
/// The representation here is 256 booleans, all initially set to false. Each
|
||||
/// boolean maps to its corresponding byte based on position. A `true` value
|
||||
/// indicates the end of an equivalence class, where its corresponding byte
|
||||
/// and all of the bytes corresponding to all previous contiguous `false`
|
||||
/// values are in the same equivalence class.
|
||||
///
|
||||
/// This particular representation only permits contiguous ranges of bytes to
|
||||
/// be in the same equivalence class, which means that we can never discover
|
||||
/// the true minimal set of equivalence classes.
|
||||
#[derive(Debug)]
|
||||
pub struct ByteClassBuilder(Vec<bool>);
|
||||
|
||||
impl ByteClassBuilder {
|
||||
/// Create a new builder of byte classes where all bytes are part of the
|
||||
/// same equivalence class.
|
||||
pub fn new() -> ByteClassBuilder {
|
||||
ByteClassBuilder(vec![false; 256])
|
||||
}
|
||||
|
||||
/// Indicate the the range of byte given (inclusive) can discriminate a
|
||||
/// match between it and all other bytes outside of the range.
|
||||
pub fn set_range(&mut self, start: u8, end: u8) {
|
||||
debug_assert!(start <= end);
|
||||
if start > 0 {
|
||||
self.0[start as usize - 1] = true;
|
||||
}
|
||||
self.0[end as usize] = true;
|
||||
}
|
||||
|
||||
/// Build byte classes that map all byte values to their corresponding
|
||||
/// equivalence class. The last mapping indicates the largest equivalence
|
||||
/// class identifier (which is never bigger than 255).
|
||||
pub fn build(&self) -> ByteClasses {
|
||||
let mut classes = ByteClasses::empty();
|
||||
let mut class = 0u8;
|
||||
let mut i = 0;
|
||||
loop {
|
||||
classes.set(i as u8, class as u8);
|
||||
if i >= 255 {
|
||||
break;
|
||||
}
|
||||
if self.0[i] {
|
||||
class = class.checked_add(1).unwrap();
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
classes
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn byte_classes() {
|
||||
let mut set = ByteClassBuilder::new();
|
||||
set.set_range(b'a', b'z');
|
||||
|
||||
let classes = set.build();
|
||||
assert_eq!(classes.get(0), 0);
|
||||
assert_eq!(classes.get(1), 0);
|
||||
assert_eq!(classes.get(2), 0);
|
||||
assert_eq!(classes.get(b'a' - 1), 0);
|
||||
assert_eq!(classes.get(b'a'), 1);
|
||||
assert_eq!(classes.get(b'm'), 1);
|
||||
assert_eq!(classes.get(b'z'), 1);
|
||||
assert_eq!(classes.get(b'z' + 1), 2);
|
||||
assert_eq!(classes.get(254), 2);
|
||||
assert_eq!(classes.get(255), 2);
|
||||
|
||||
let mut set = ByteClassBuilder::new();
|
||||
set.set_range(0, 2);
|
||||
set.set_range(4, 6);
|
||||
let classes = set.build();
|
||||
assert_eq!(classes.get(0), 0);
|
||||
assert_eq!(classes.get(1), 0);
|
||||
assert_eq!(classes.get(2), 0);
|
||||
assert_eq!(classes.get(3), 1);
|
||||
assert_eq!(classes.get(4), 2);
|
||||
assert_eq!(classes.get(5), 2);
|
||||
assert_eq!(classes.get(6), 2);
|
||||
assert_eq!(classes.get(7), 3);
|
||||
assert_eq!(classes.get(255), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_byte_classes() {
|
||||
let mut set = ByteClassBuilder::new();
|
||||
for i in 0..256u16 {
|
||||
set.set_range(i as u8, i as u8);
|
||||
}
|
||||
assert_eq!(set.build().alphabet_len(), 256);
|
||||
}
|
||||
}
|
||||
713
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/dfa.rs
vendored
Normal file
713
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/dfa.rs
vendored
Normal file
@@ -0,0 +1,713 @@
|
||||
use std::mem::size_of;
|
||||
|
||||
use crate::ahocorasick::MatchKind;
|
||||
use crate::automaton::Automaton;
|
||||
use crate::classes::ByteClasses;
|
||||
use crate::error::Result;
|
||||
use crate::nfa::{PatternID, PatternLength, NFA};
|
||||
use crate::prefilter::{Prefilter, PrefilterObj, PrefilterState};
|
||||
use crate::state_id::{dead_id, fail_id, premultiply_overflow_error, StateID};
|
||||
use crate::Match;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DFA<S> {
|
||||
Standard(Standard<S>),
|
||||
ByteClass(ByteClass<S>),
|
||||
Premultiplied(Premultiplied<S>),
|
||||
PremultipliedByteClass(PremultipliedByteClass<S>),
|
||||
}
|
||||
|
||||
impl<S: StateID> DFA<S> {
|
||||
fn repr(&self) -> &Repr<S> {
|
||||
match *self {
|
||||
DFA::Standard(ref dfa) => dfa.repr(),
|
||||
DFA::ByteClass(ref dfa) => dfa.repr(),
|
||||
DFA::Premultiplied(ref dfa) => dfa.repr(),
|
||||
DFA::PremultipliedByteClass(ref dfa) => dfa.repr(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn match_kind(&self) -> &MatchKind {
|
||||
&self.repr().match_kind
|
||||
}
|
||||
|
||||
pub fn heap_bytes(&self) -> usize {
|
||||
self.repr().heap_bytes
|
||||
}
|
||||
|
||||
pub fn max_pattern_len(&self) -> usize {
|
||||
self.repr().max_pattern_len
|
||||
}
|
||||
|
||||
pub fn pattern_count(&self) -> usize {
|
||||
self.repr().pattern_count
|
||||
}
|
||||
|
||||
pub fn prefilter(&self) -> Option<&dyn Prefilter> {
|
||||
self.repr().prefilter.as_ref().map(|p| p.as_ref())
|
||||
}
|
||||
|
||||
pub fn start_state(&self) -> S {
|
||||
self.repr().start_id
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn overlapping_find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut S,
|
||||
match_index: &mut usize,
|
||||
) -> Option<Match> {
|
||||
match *self {
|
||||
DFA::Standard(ref dfa) => dfa.overlapping_find_at(
|
||||
prestate,
|
||||
haystack,
|
||||
at,
|
||||
state_id,
|
||||
match_index,
|
||||
),
|
||||
DFA::ByteClass(ref dfa) => dfa.overlapping_find_at(
|
||||
prestate,
|
||||
haystack,
|
||||
at,
|
||||
state_id,
|
||||
match_index,
|
||||
),
|
||||
DFA::Premultiplied(ref dfa) => dfa.overlapping_find_at(
|
||||
prestate,
|
||||
haystack,
|
||||
at,
|
||||
state_id,
|
||||
match_index,
|
||||
),
|
||||
DFA::PremultipliedByteClass(ref dfa) => dfa.overlapping_find_at(
|
||||
prestate,
|
||||
haystack,
|
||||
at,
|
||||
state_id,
|
||||
match_index,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn earliest_find_at(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
state_id: &mut S,
|
||||
) -> Option<Match> {
|
||||
match *self {
|
||||
DFA::Standard(ref dfa) => {
|
||||
dfa.earliest_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
DFA::ByteClass(ref dfa) => {
|
||||
dfa.earliest_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
DFA::Premultiplied(ref dfa) => {
|
||||
dfa.earliest_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
DFA::PremultipliedByteClass(ref dfa) => {
|
||||
dfa.earliest_find_at(prestate, haystack, at, state_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn find_at_no_state(
|
||||
&self,
|
||||
prestate: &mut PrefilterState,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
) -> Option<Match> {
|
||||
match *self {
|
||||
DFA::Standard(ref dfa) => {
|
||||
dfa.find_at_no_state(prestate, haystack, at)
|
||||
}
|
||||
DFA::ByteClass(ref dfa) => {
|
||||
dfa.find_at_no_state(prestate, haystack, at)
|
||||
}
|
||||
DFA::Premultiplied(ref dfa) => {
|
||||
dfa.find_at_no_state(prestate, haystack, at)
|
||||
}
|
||||
DFA::PremultipliedByteClass(ref dfa) => {
|
||||
dfa.find_at_no_state(prestate, haystack, at)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Standard<S>(Repr<S>);
|
||||
|
||||
impl<S: StateID> Standard<S> {
|
||||
fn repr(&self) -> &Repr<S> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: StateID> Automaton for Standard<S> {
|
||||
type ID = S;
|
||||
|
||||
fn match_kind(&self) -> &MatchKind {
|
||||
&self.repr().match_kind
|
||||
}
|
||||
|
||||
fn anchored(&self) -> bool {
|
||||
self.repr().anchored
|
||||
}
|
||||
|
||||
fn prefilter(&self) -> Option<&dyn Prefilter> {
|
||||
self.repr().prefilter.as_ref().map(|p| p.as_ref())
|
||||
}
|
||||
|
||||
fn start_state(&self) -> S {
|
||||
self.repr().start_id
|
||||
}
|
||||
|
||||
fn is_valid(&self, id: S) -> bool {
|
||||
id.to_usize() < self.repr().state_count
|
||||
}
|
||||
|
||||
fn is_match_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_state(id)
|
||||
}
|
||||
|
||||
fn is_match_or_dead_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_or_dead_state(id)
|
||||
}
|
||||
|
||||
fn get_match(
|
||||
&self,
|
||||
id: S,
|
||||
match_index: usize,
|
||||
end: usize,
|
||||
) -> Option<Match> {
|
||||
self.repr().get_match(id, match_index, end)
|
||||
}
|
||||
|
||||
fn match_count(&self, id: S) -> usize {
|
||||
self.repr().match_count(id)
|
||||
}
|
||||
|
||||
fn next_state(&self, current: S, input: u8) -> S {
|
||||
let o = current.to_usize() * 256 + input as usize;
|
||||
self.repr().trans[o]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ByteClass<S>(Repr<S>);
|
||||
|
||||
impl<S: StateID> ByteClass<S> {
|
||||
fn repr(&self) -> &Repr<S> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: StateID> Automaton for ByteClass<S> {
|
||||
type ID = S;
|
||||
|
||||
fn match_kind(&self) -> &MatchKind {
|
||||
&self.repr().match_kind
|
||||
}
|
||||
|
||||
fn anchored(&self) -> bool {
|
||||
self.repr().anchored
|
||||
}
|
||||
|
||||
fn prefilter(&self) -> Option<&dyn Prefilter> {
|
||||
self.repr().prefilter.as_ref().map(|p| p.as_ref())
|
||||
}
|
||||
|
||||
fn start_state(&self) -> S {
|
||||
self.repr().start_id
|
||||
}
|
||||
|
||||
fn is_valid(&self, id: S) -> bool {
|
||||
id.to_usize() < self.repr().state_count
|
||||
}
|
||||
|
||||
fn is_match_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_state(id)
|
||||
}
|
||||
|
||||
fn is_match_or_dead_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_or_dead_state(id)
|
||||
}
|
||||
|
||||
fn get_match(
|
||||
&self,
|
||||
id: S,
|
||||
match_index: usize,
|
||||
end: usize,
|
||||
) -> Option<Match> {
|
||||
self.repr().get_match(id, match_index, end)
|
||||
}
|
||||
|
||||
fn match_count(&self, id: S) -> usize {
|
||||
self.repr().match_count(id)
|
||||
}
|
||||
|
||||
fn next_state(&self, current: S, input: u8) -> S {
|
||||
let alphabet_len = self.repr().byte_classes.alphabet_len();
|
||||
let input = self.repr().byte_classes.get(input);
|
||||
let o = current.to_usize() * alphabet_len + input as usize;
|
||||
self.repr().trans[o]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Premultiplied<S>(Repr<S>);
|
||||
|
||||
impl<S: StateID> Premultiplied<S> {
|
||||
fn repr(&self) -> &Repr<S> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: StateID> Automaton for Premultiplied<S> {
|
||||
type ID = S;
|
||||
|
||||
fn match_kind(&self) -> &MatchKind {
|
||||
&self.repr().match_kind
|
||||
}
|
||||
|
||||
fn anchored(&self) -> bool {
|
||||
self.repr().anchored
|
||||
}
|
||||
|
||||
fn prefilter(&self) -> Option<&dyn Prefilter> {
|
||||
self.repr().prefilter.as_ref().map(|p| p.as_ref())
|
||||
}
|
||||
|
||||
fn start_state(&self) -> S {
|
||||
self.repr().start_id
|
||||
}
|
||||
|
||||
fn is_valid(&self, id: S) -> bool {
|
||||
(id.to_usize() / 256) < self.repr().state_count
|
||||
}
|
||||
|
||||
fn is_match_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_state(id)
|
||||
}
|
||||
|
||||
fn is_match_or_dead_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_or_dead_state(id)
|
||||
}
|
||||
|
||||
fn get_match(
|
||||
&self,
|
||||
id: S,
|
||||
match_index: usize,
|
||||
end: usize,
|
||||
) -> Option<Match> {
|
||||
if id > self.repr().max_match {
|
||||
return None;
|
||||
}
|
||||
self.repr()
|
||||
.matches
|
||||
.get(id.to_usize() / 256)
|
||||
.and_then(|m| m.get(match_index))
|
||||
.map(|&(id, len)| Match { pattern: id, len, end })
|
||||
}
|
||||
|
||||
fn match_count(&self, id: S) -> usize {
|
||||
let o = id.to_usize() / 256;
|
||||
self.repr().matches[o].len()
|
||||
}
|
||||
|
||||
fn next_state(&self, current: S, input: u8) -> S {
|
||||
let o = current.to_usize() + input as usize;
|
||||
self.repr().trans[o]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PremultipliedByteClass<S>(Repr<S>);
|
||||
|
||||
impl<S: StateID> PremultipliedByteClass<S> {
|
||||
fn repr(&self) -> &Repr<S> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: StateID> Automaton for PremultipliedByteClass<S> {
|
||||
type ID = S;
|
||||
|
||||
fn match_kind(&self) -> &MatchKind {
|
||||
&self.repr().match_kind
|
||||
}
|
||||
|
||||
fn anchored(&self) -> bool {
|
||||
self.repr().anchored
|
||||
}
|
||||
|
||||
fn prefilter(&self) -> Option<&dyn Prefilter> {
|
||||
self.repr().prefilter.as_ref().map(|p| p.as_ref())
|
||||
}
|
||||
|
||||
fn start_state(&self) -> S {
|
||||
self.repr().start_id
|
||||
}
|
||||
|
||||
fn is_valid(&self, id: S) -> bool {
|
||||
(id.to_usize() / self.repr().alphabet_len()) < self.repr().state_count
|
||||
}
|
||||
|
||||
fn is_match_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_state(id)
|
||||
}
|
||||
|
||||
fn is_match_or_dead_state(&self, id: S) -> bool {
|
||||
self.repr().is_match_or_dead_state(id)
|
||||
}
|
||||
|
||||
fn get_match(
|
||||
&self,
|
||||
id: S,
|
||||
match_index: usize,
|
||||
end: usize,
|
||||
) -> Option<Match> {
|
||||
if id > self.repr().max_match {
|
||||
return None;
|
||||
}
|
||||
self.repr()
|
||||
.matches
|
||||
.get(id.to_usize() / self.repr().alphabet_len())
|
||||
.and_then(|m| m.get(match_index))
|
||||
.map(|&(id, len)| Match { pattern: id, len, end })
|
||||
}
|
||||
|
||||
fn match_count(&self, id: S) -> usize {
|
||||
let o = id.to_usize() / self.repr().alphabet_len();
|
||||
self.repr().matches[o].len()
|
||||
}
|
||||
|
||||
fn next_state(&self, current: S, input: u8) -> S {
|
||||
let input = self.repr().byte_classes.get(input);
|
||||
let o = current.to_usize() + input as usize;
|
||||
self.repr().trans[o]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Repr<S> {
|
||||
match_kind: MatchKind,
|
||||
anchored: bool,
|
||||
premultiplied: bool,
|
||||
start_id: S,
|
||||
/// The length, in bytes, of the longest pattern in this automaton. This
|
||||
/// information is useful for keeping correct buffer sizes when searching
|
||||
/// on streams.
|
||||
max_pattern_len: usize,
|
||||
/// The total number of patterns added to this automaton. This includes
|
||||
/// patterns that may never match.
|
||||
pattern_count: usize,
|
||||
state_count: usize,
|
||||
max_match: S,
|
||||
/// The number of bytes of heap used by this NFA's transition table.
|
||||
heap_bytes: usize,
|
||||
/// A prefilter for quickly detecting candidate matchs, if pertinent.
|
||||
prefilter: Option<PrefilterObj>,
|
||||
byte_classes: ByteClasses,
|
||||
trans: Vec<S>,
|
||||
matches: Vec<Vec<(PatternID, PatternLength)>>,
|
||||
}
|
||||
|
||||
impl<S: StateID> Repr<S> {
|
||||
/// Returns the total alphabet size for this DFA.
|
||||
///
|
||||
/// If byte classes are enabled, then this corresponds to the number of
|
||||
/// equivalence classes. If they are disabled, then this is always 256.
|
||||
fn alphabet_len(&self) -> usize {
|
||||
self.byte_classes.alphabet_len()
|
||||
}
|
||||
|
||||
/// Returns true only if the given state is a match state.
|
||||
fn is_match_state(&self, id: S) -> bool {
|
||||
id <= self.max_match && id > dead_id()
|
||||
}
|
||||
|
||||
/// Returns true only if the given state is either a dead state or a match
|
||||
/// state.
|
||||
fn is_match_or_dead_state(&self, id: S) -> bool {
|
||||
id <= self.max_match
|
||||
}
|
||||
|
||||
/// Get the ith match for the given state, where the end position of a
|
||||
/// match was found at `end`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The caller must ensure that the given state identifier is valid,
|
||||
/// otherwise this may panic. The `match_index` need not be valid. That is,
|
||||
/// if the given state has no matches then this returns `None`.
|
||||
fn get_match(
|
||||
&self,
|
||||
id: S,
|
||||
match_index: usize,
|
||||
end: usize,
|
||||
) -> Option<Match> {
|
||||
if id > self.max_match {
|
||||
return None;
|
||||
}
|
||||
self.matches
|
||||
.get(id.to_usize())
|
||||
.and_then(|m| m.get(match_index))
|
||||
.map(|&(id, len)| Match { pattern: id, len, end })
|
||||
}
|
||||
|
||||
/// Return the total number of matches for the given state.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The caller must ensure that the given identifier is valid, or else
|
||||
/// this panics.
|
||||
fn match_count(&self, id: S) -> usize {
|
||||
self.matches[id.to_usize()].len()
|
||||
}
|
||||
|
||||
/// Get the next state given `from` as the current state and `byte` as the
|
||||
/// current input byte.
|
||||
fn next_state(&self, from: S, byte: u8) -> S {
|
||||
let alphabet_len = self.alphabet_len();
|
||||
let byte = self.byte_classes.get(byte);
|
||||
self.trans[from.to_usize() * alphabet_len + byte as usize]
|
||||
}
|
||||
|
||||
/// Set the `byte` transition for the `from` state to point to `to`.
|
||||
fn set_next_state(&mut self, from: S, byte: u8, to: S) {
|
||||
let alphabet_len = self.alphabet_len();
|
||||
let byte = self.byte_classes.get(byte);
|
||||
self.trans[from.to_usize() * alphabet_len + byte as usize] = to;
|
||||
}
|
||||
|
||||
/// Swap the given states in place.
|
||||
fn swap_states(&mut self, id1: S, id2: S) {
|
||||
assert!(!self.premultiplied, "can't swap states in premultiplied DFA");
|
||||
|
||||
let o1 = id1.to_usize() * self.alphabet_len();
|
||||
let o2 = id2.to_usize() * self.alphabet_len();
|
||||
for b in 0..self.alphabet_len() {
|
||||
self.trans.swap(o1 + b, o2 + b);
|
||||
}
|
||||
self.matches.swap(id1.to_usize(), id2.to_usize());
|
||||
}
|
||||
|
||||
/// This routine shuffles all match states in this DFA to the beginning
|
||||
/// of the DFA such that every non-match state appears after every match
|
||||
/// state. (With one exception: the special fail and dead states remain as
|
||||
/// the first two states.)
|
||||
///
|
||||
/// The purpose of doing this shuffling is to avoid an extra conditional
|
||||
/// in the search loop, and in particular, detecting whether a state is a
|
||||
/// match or not does not need to access any memory.
|
||||
///
|
||||
/// This updates `self.max_match` to point to the last matching state as
|
||||
/// well as `self.start` if the starting state was moved.
|
||||
fn shuffle_match_states(&mut self) {
|
||||
assert!(
|
||||
!self.premultiplied,
|
||||
"cannot shuffle match states of premultiplied DFA"
|
||||
);
|
||||
|
||||
if self.state_count <= 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut first_non_match = self.start_id.to_usize();
|
||||
while first_non_match < self.state_count
|
||||
&& self.matches[first_non_match].len() > 0
|
||||
{
|
||||
first_non_match += 1;
|
||||
}
|
||||
|
||||
let mut swaps: Vec<S> = vec![fail_id(); self.state_count];
|
||||
let mut cur = self.state_count - 1;
|
||||
while cur > first_non_match {
|
||||
if self.matches[cur].len() > 0 {
|
||||
self.swap_states(
|
||||
S::from_usize(cur),
|
||||
S::from_usize(first_non_match),
|
||||
);
|
||||
swaps[cur] = S::from_usize(first_non_match);
|
||||
swaps[first_non_match] = S::from_usize(cur);
|
||||
|
||||
first_non_match += 1;
|
||||
while first_non_match < cur
|
||||
&& self.matches[first_non_match].len() > 0
|
||||
{
|
||||
first_non_match += 1;
|
||||
}
|
||||
}
|
||||
cur -= 1;
|
||||
}
|
||||
for id in (0..self.state_count).map(S::from_usize) {
|
||||
let alphabet_len = self.alphabet_len();
|
||||
let offset = id.to_usize() * alphabet_len;
|
||||
for next in &mut self.trans[offset..offset + alphabet_len] {
|
||||
if swaps[next.to_usize()] != fail_id() {
|
||||
*next = swaps[next.to_usize()];
|
||||
}
|
||||
}
|
||||
}
|
||||
if swaps[self.start_id.to_usize()] != fail_id() {
|
||||
self.start_id = swaps[self.start_id.to_usize()];
|
||||
}
|
||||
self.max_match = S::from_usize(first_non_match - 1);
|
||||
}
|
||||
|
||||
fn premultiply(&mut self) -> Result<()> {
|
||||
if self.premultiplied || self.state_count <= 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let alpha_len = self.alphabet_len();
|
||||
premultiply_overflow_error(
|
||||
S::from_usize(self.state_count - 1),
|
||||
alpha_len,
|
||||
)?;
|
||||
|
||||
for id in (2..self.state_count).map(S::from_usize) {
|
||||
let offset = id.to_usize() * alpha_len;
|
||||
for next in &mut self.trans[offset..offset + alpha_len] {
|
||||
if *next == dead_id() {
|
||||
continue;
|
||||
}
|
||||
*next = S::from_usize(next.to_usize() * alpha_len);
|
||||
}
|
||||
}
|
||||
self.premultiplied = true;
|
||||
self.start_id = S::from_usize(self.start_id.to_usize() * alpha_len);
|
||||
self.max_match = S::from_usize(self.max_match.to_usize() * alpha_len);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Computes the total amount of heap used by this NFA in bytes.
|
||||
fn calculate_size(&mut self) {
|
||||
let mut size = (self.trans.len() * size_of::<S>())
|
||||
+ (self.matches.len()
|
||||
* size_of::<Vec<(PatternID, PatternLength)>>());
|
||||
for state_matches in &self.matches {
|
||||
size +=
|
||||
state_matches.len() * size_of::<(PatternID, PatternLength)>();
|
||||
}
|
||||
size += self.prefilter.as_ref().map_or(0, |p| p.as_ref().heap_bytes());
|
||||
self.heap_bytes = size;
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for configuring the determinization of an NFA into a DFA.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Builder {
|
||||
premultiply: bool,
|
||||
byte_classes: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Create a new builder for a DFA.
|
||||
pub fn new() -> Builder {
|
||||
Builder { premultiply: true, byte_classes: true }
|
||||
}
|
||||
|
||||
/// Build a DFA from the given NFA.
|
||||
///
|
||||
/// This returns an error if the state identifiers exceed their
|
||||
/// representation size. This can only happen when state ids are
|
||||
/// premultiplied (which is enabled by default).
|
||||
pub fn build<S: StateID>(&self, nfa: &NFA<S>) -> Result<DFA<S>> {
|
||||
let byte_classes = if self.byte_classes {
|
||||
nfa.byte_classes().clone()
|
||||
} else {
|
||||
ByteClasses::singletons()
|
||||
};
|
||||
let alphabet_len = byte_classes.alphabet_len();
|
||||
let trans = vec![fail_id(); alphabet_len * nfa.state_len()];
|
||||
let matches = vec![vec![]; nfa.state_len()];
|
||||
let mut repr = Repr {
|
||||
match_kind: nfa.match_kind().clone(),
|
||||
anchored: nfa.anchored(),
|
||||
premultiplied: false,
|
||||
start_id: nfa.start_state(),
|
||||
max_pattern_len: nfa.max_pattern_len(),
|
||||
pattern_count: nfa.pattern_count(),
|
||||
state_count: nfa.state_len(),
|
||||
max_match: fail_id(),
|
||||
heap_bytes: 0,
|
||||
prefilter: nfa.prefilter_obj().map(|p| p.clone()),
|
||||
byte_classes: byte_classes.clone(),
|
||||
trans,
|
||||
matches,
|
||||
};
|
||||
for id in (0..nfa.state_len()).map(S::from_usize) {
|
||||
repr.matches[id.to_usize()].extend_from_slice(nfa.matches(id));
|
||||
|
||||
let fail = nfa.failure_transition(id);
|
||||
nfa.iter_all_transitions(&byte_classes, id, |b, mut next| {
|
||||
if next == fail_id() {
|
||||
next = nfa_next_state_memoized(nfa, &repr, id, fail, b);
|
||||
}
|
||||
repr.set_next_state(id, b, next);
|
||||
});
|
||||
}
|
||||
repr.shuffle_match_states();
|
||||
repr.calculate_size();
|
||||
if self.premultiply {
|
||||
repr.premultiply()?;
|
||||
if byte_classes.is_singleton() {
|
||||
Ok(DFA::Premultiplied(Premultiplied(repr)))
|
||||
} else {
|
||||
Ok(DFA::PremultipliedByteClass(PremultipliedByteClass(repr)))
|
||||
}
|
||||
} else {
|
||||
if byte_classes.is_singleton() {
|
||||
Ok(DFA::Standard(Standard(repr)))
|
||||
} else {
|
||||
Ok(DFA::ByteClass(ByteClass(repr)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to use byte classes or in the DFA.
|
||||
pub fn byte_classes(&mut self, yes: bool) -> &mut Builder {
|
||||
self.byte_classes = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether to premultiply state identifier in the DFA.
|
||||
pub fn premultiply(&mut self, yes: bool) -> &mut Builder {
|
||||
self.premultiply = yes;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// This returns the next NFA transition (including resolving failure
|
||||
/// transitions), except once it sees a state id less than the id of the DFA
|
||||
/// state that is currently being populated, then we no longer need to follow
|
||||
/// failure transitions and can instead query the pre-computed state id from
|
||||
/// the DFA itself.
|
||||
///
|
||||
/// In general, this should only be called when a failure transition is seen.
|
||||
fn nfa_next_state_memoized<S: StateID>(
|
||||
nfa: &NFA<S>,
|
||||
dfa: &Repr<S>,
|
||||
populating: S,
|
||||
mut current: S,
|
||||
input: u8,
|
||||
) -> S {
|
||||
loop {
|
||||
if current < populating {
|
||||
return dfa.next_state(current, input);
|
||||
}
|
||||
let next = nfa.next_state(current, input);
|
||||
if next != fail_id() {
|
||||
return next;
|
||||
}
|
||||
current = nfa.failure_transition(current);
|
||||
}
|
||||
}
|
||||
101
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/error.rs
vendored
Normal file
101
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/error.rs
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::result;
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// An error that occurred during the construction of an Aho-Corasick
|
||||
/// automaton.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Error {
|
||||
kind: ErrorKind,
|
||||
}
|
||||
|
||||
/// The kind of error that occurred.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ErrorKind {
|
||||
/// An error that occurs when constructing an automaton would require the
|
||||
/// use of a state ID that overflows the chosen state ID representation.
|
||||
/// For example, if one is using `u8` for state IDs and builds a DFA with
|
||||
/// 257 states, then the last state's ID will be `256` which cannot be
|
||||
/// represented with `u8`.
|
||||
StateIDOverflow {
|
||||
/// The maximum possible state ID.
|
||||
max: usize,
|
||||
},
|
||||
/// An error that occurs when premultiplication of state IDs is requested
|
||||
/// when constructing an Aho-Corasick DFA, but doing so would overflow the
|
||||
/// chosen state ID representation.
|
||||
///
|
||||
/// When `max == requested_max`, then the state ID would overflow `usize`.
|
||||
PremultiplyOverflow {
|
||||
/// The maximum possible state id.
|
||||
max: usize,
|
||||
/// The maximum ID required by premultiplication.
|
||||
requested_max: usize,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Return the kind of this error.
|
||||
pub fn kind(&self) -> &ErrorKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub(crate) fn state_id_overflow(max: usize) -> Error {
|
||||
Error { kind: ErrorKind::StateIDOverflow { max } }
|
||||
}
|
||||
|
||||
pub(crate) fn premultiply_overflow(
|
||||
max: usize,
|
||||
requested_max: usize,
|
||||
) -> Error {
|
||||
Error { kind: ErrorKind::PremultiplyOverflow { max, requested_max } }
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match self.kind {
|
||||
ErrorKind::StateIDOverflow { .. } => {
|
||||
"state id representation too small"
|
||||
}
|
||||
ErrorKind::PremultiplyOverflow { .. } => {
|
||||
"state id representation too small for premultiplication"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind {
|
||||
ErrorKind::StateIDOverflow { max } => write!(
|
||||
f,
|
||||
"building the automaton failed because it required \
|
||||
building more states that can be identified, where the \
|
||||
maximum ID for the chosen representation is {}",
|
||||
max,
|
||||
),
|
||||
ErrorKind::PremultiplyOverflow { max, requested_max } => {
|
||||
if max == requested_max {
|
||||
write!(
|
||||
f,
|
||||
"premultiplication of states requires the ability to \
|
||||
represent a state ID greater than what can fit on \
|
||||
this platform's usize, which is {}",
|
||||
::std::usize::MAX,
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"premultiplication of states requires the ability to \
|
||||
represent at least a state ID of {}, but the chosen \
|
||||
representation only permits a maximum state ID of {}",
|
||||
requested_max, max,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
303
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/lib.rs
vendored
Normal file
303
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/lib.rs
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
/*!
|
||||
A library for finding occurrences of many patterns at once. This library
|
||||
provides multiple pattern search principally through an implementation of the
|
||||
[Aho-Corasick algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm),
|
||||
which builds a fast finite state machine for executing searches in linear time.
|
||||
|
||||
Additionally, this library provides a number of configuration options for
|
||||
building the automaton that permit controlling the space versus time trade
|
||||
off. Other features include simple ASCII case insensitive matching, finding
|
||||
overlapping matches, replacements, searching streams and even searching and
|
||||
replacing text in streams.
|
||||
|
||||
Finally, unlike all other (known) Aho-Corasick implementations, this one
|
||||
supports enabling
|
||||
[leftmost-first](enum.MatchKind.html#variant.LeftmostFirst)
|
||||
or
|
||||
[leftmost-longest](enum.MatchKind.html#variant.LeftmostFirst)
|
||||
match semantics, using a (seemingly) novel alternative construction algorithm.
|
||||
For more details on what match semantics means, see the
|
||||
[`MatchKind`](enum.MatchKind.html)
|
||||
type.
|
||||
|
||||
# Overview
|
||||
|
||||
This section gives a brief overview of the primary types in this crate:
|
||||
|
||||
* [`AhoCorasick`](struct.AhoCorasick.html) is the primary type and represents
|
||||
an Aho-Corasick automaton. This is the type you use to execute searches.
|
||||
* [`AhoCorasickBuilder`](struct.AhoCorasickBuilder.html) can be used to build
|
||||
an Aho-Corasick automaton, and supports configuring a number of options.
|
||||
* [`Match`](struct.Match.html) represents a single match reported by an
|
||||
Aho-Corasick automaton. Each match has two pieces of information: the pattern
|
||||
that matched and the start and end byte offsets corresponding to the position
|
||||
in the haystack at which it matched.
|
||||
|
||||
Additionally, the [`packed`](packed/index.html) sub-module contains a lower
|
||||
level API for using fast vectorized routines for finding a small number of
|
||||
patterns in a haystack.
|
||||
|
||||
# Example: basic searching
|
||||
|
||||
This example shows how to search for occurrences of multiple patterns
|
||||
simultaneously. Each match includes the pattern that matched along with the
|
||||
byte offsets of the match.
|
||||
|
||||
```
|
||||
use aho_corasick::AhoCorasick;
|
||||
|
||||
let patterns = &["apple", "maple", "Snapple"];
|
||||
let haystack = "Nobody likes maple in their apple flavored Snapple.";
|
||||
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
let mut matches = vec![];
|
||||
for mat in ac.find_iter(haystack) {
|
||||
matches.push((mat.pattern(), mat.start(), mat.end()));
|
||||
}
|
||||
assert_eq!(matches, vec![
|
||||
(1, 13, 18),
|
||||
(0, 28, 33),
|
||||
(2, 43, 50),
|
||||
]);
|
||||
```
|
||||
|
||||
# Example: case insensitivity
|
||||
|
||||
This is like the previous example, but matches `Snapple` case insensitively
|
||||
using `AhoCorasickBuilder`:
|
||||
|
||||
```
|
||||
use aho_corasick::AhoCorasickBuilder;
|
||||
|
||||
let patterns = &["apple", "maple", "snapple"];
|
||||
let haystack = "Nobody likes maple in their apple flavored Snapple.";
|
||||
|
||||
let ac = AhoCorasickBuilder::new()
|
||||
.ascii_case_insensitive(true)
|
||||
.build(patterns);
|
||||
let mut matches = vec![];
|
||||
for mat in ac.find_iter(haystack) {
|
||||
matches.push((mat.pattern(), mat.start(), mat.end()));
|
||||
}
|
||||
assert_eq!(matches, vec![
|
||||
(1, 13, 18),
|
||||
(0, 28, 33),
|
||||
(2, 43, 50),
|
||||
]);
|
||||
```
|
||||
|
||||
# Example: replacing matches in a stream
|
||||
|
||||
This example shows how to execute a search and replace on a stream without
|
||||
loading the entire stream into memory first.
|
||||
|
||||
```
|
||||
use aho_corasick::AhoCorasick;
|
||||
|
||||
# fn example() -> Result<(), ::std::io::Error> {
|
||||
let patterns = &["fox", "brown", "quick"];
|
||||
let replace_with = &["sloth", "grey", "slow"];
|
||||
|
||||
// In a real example, these might be `std::fs::File`s instead. All you need to
|
||||
// do is supply a pair of `std::io::Read` and `std::io::Write` implementations.
|
||||
let rdr = "The quick brown fox.";
|
||||
let mut wtr = vec![];
|
||||
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
ac.stream_replace_all(rdr.as_bytes(), &mut wtr, replace_with)?;
|
||||
assert_eq!(b"The slow grey sloth.".to_vec(), wtr);
|
||||
# Ok(()) }; example().unwrap()
|
||||
```
|
||||
|
||||
# Example: finding the leftmost first match
|
||||
|
||||
In the textbook description of Aho-Corasick, its formulation is typically
|
||||
structured such that it reports all possible matches, even when they overlap
|
||||
with another. In many cases, overlapping matches may not be desired, such as
|
||||
the case of finding all successive non-overlapping matches like you might with
|
||||
a standard regular expression.
|
||||
|
||||
Unfortunately the "obvious" way to modify the Aho-Corasick algorithm to do
|
||||
this doesn't always work in the expected way, since it will report matches as
|
||||
soon as they are seen. For example, consider matching the regex `Samwise|Sam`
|
||||
against the text `Samwise`. Most regex engines (that are Perl-like, or
|
||||
non-POSIX) will report `Samwise` as a match, but the standard Aho-Corasick
|
||||
algorithm modified for reporting non-overlapping matches will report `Sam`.
|
||||
|
||||
A novel contribution of this library is the ability to change the match
|
||||
semantics of Aho-Corasick (without additional search time overhead) such that
|
||||
`Samwise` is reported instead. For example, here's the standard approach:
|
||||
|
||||
```
|
||||
use aho_corasick::AhoCorasick;
|
||||
|
||||
let patterns = &["Samwise", "Sam"];
|
||||
let haystack = "Samwise";
|
||||
|
||||
let ac = AhoCorasick::new(patterns);
|
||||
let mat = ac.find(haystack).expect("should have a match");
|
||||
assert_eq!("Sam", &haystack[mat.start()..mat.end()]);
|
||||
```
|
||||
|
||||
And now here's the leftmost-first version, which matches how a Perl-like
|
||||
regex will work:
|
||||
|
||||
```
|
||||
use aho_corasick::{AhoCorasickBuilder, MatchKind};
|
||||
|
||||
let patterns = &["Samwise", "Sam"];
|
||||
let haystack = "Samwise";
|
||||
|
||||
let ac = AhoCorasickBuilder::new()
|
||||
.match_kind(MatchKind::LeftmostFirst)
|
||||
.build(patterns);
|
||||
let mat = ac.find(haystack).expect("should have a match");
|
||||
assert_eq!("Samwise", &haystack[mat.start()..mat.end()]);
|
||||
```
|
||||
|
||||
In addition to leftmost-first semantics, this library also supports
|
||||
leftmost-longest semantics, which match the POSIX behavior of a regular
|
||||
expression alternation. See
|
||||
[`MatchKind`](enum.MatchKind.html)
|
||||
for more details.
|
||||
|
||||
# Prefilters
|
||||
|
||||
While an Aho-Corasick automaton can perform admirably when compared to more
|
||||
naive solutions, it is generally slower than more specialized algorithms that
|
||||
are accelerated using vector instructions such as SIMD.
|
||||
|
||||
For that reason, this library will internally use a "prefilter" to attempt
|
||||
to accelerate searches when possible. Currently, this library has several
|
||||
different algorithms it might use depending on the patterns provided. Once the
|
||||
number of patterns gets too big, prefilters are no longer used.
|
||||
|
||||
While a prefilter is generally good to have on by default since it works
|
||||
well in the common case, it can lead to less predictable or even sub-optimal
|
||||
performance in some cases. For that reason, prefilters can be explicitly
|
||||
disabled via
|
||||
[`AhoCorasickBuilder::prefilter`](struct.AhoCorasickBuilder.html#method.prefilter).
|
||||
*/
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
// We can never be truly no_std, but we could be alloc-only some day, so
|
||||
// require the std feature for now.
|
||||
#[cfg(not(feature = "std"))]
|
||||
compile_error!("`std` feature is currently required to build this crate");
|
||||
|
||||
// #[cfg(doctest)]
|
||||
// #[macro_use]
|
||||
// extern crate doc_comment;
|
||||
|
||||
// #[cfg(doctest)]
|
||||
// doctest!("../README.md");
|
||||
|
||||
pub use crate::ahocorasick::{
|
||||
AhoCorasick, AhoCorasickBuilder, FindIter, FindOverlappingIter, MatchKind,
|
||||
StreamFindIter,
|
||||
};
|
||||
pub use crate::error::{Error, ErrorKind};
|
||||
pub use crate::state_id::StateID;
|
||||
|
||||
mod ahocorasick;
|
||||
mod automaton;
|
||||
mod buffer;
|
||||
mod byte_frequencies;
|
||||
mod classes;
|
||||
mod dfa;
|
||||
mod error;
|
||||
mod nfa;
|
||||
pub mod packed;
|
||||
mod prefilter;
|
||||
mod state_id;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// A representation of a match reported by an Aho-Corasick automaton.
|
||||
///
|
||||
/// A match has two essential pieces of information: the identifier of the
|
||||
/// pattern that matched, along with the start and end offsets of the match
|
||||
/// in the haystack.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::AhoCorasick;
|
||||
///
|
||||
/// let ac = AhoCorasick::new(&[
|
||||
/// "foo", "bar", "baz",
|
||||
/// ]);
|
||||
/// let mat = ac.find("xxx bar xxx").expect("should have a match");
|
||||
/// assert_eq!(1, mat.pattern());
|
||||
/// assert_eq!(4, mat.start());
|
||||
/// assert_eq!(7, mat.end());
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Match {
|
||||
/// The pattern id.
|
||||
pattern: usize,
|
||||
/// The length of this match, such that the starting position of the match
|
||||
/// is `end - len`.
|
||||
///
|
||||
/// We use length here because, other than the pattern id, the only
|
||||
/// information about each pattern that the automaton stores is its length.
|
||||
/// So using the length here is just a bit more natural. But it isn't
|
||||
/// technically required.
|
||||
len: usize,
|
||||
/// The end offset of the match, exclusive.
|
||||
end: usize,
|
||||
}
|
||||
|
||||
impl Match {
|
||||
/// Returns the identifier of the pattern that matched.
|
||||
///
|
||||
/// The identifier of a pattern is derived from the position in which it
|
||||
/// was originally inserted into the corresponding automaton. The first
|
||||
/// pattern has identifier `0`, and each subsequent pattern is `1`, `2`
|
||||
/// and so on.
|
||||
#[inline]
|
||||
pub fn pattern(&self) -> usize {
|
||||
self.pattern
|
||||
}
|
||||
|
||||
/// The starting position of the match.
|
||||
#[inline]
|
||||
pub fn start(&self) -> usize {
|
||||
self.end - self.len
|
||||
}
|
||||
|
||||
/// The ending position of the match.
|
||||
#[inline]
|
||||
pub fn end(&self) -> usize {
|
||||
self.end
|
||||
}
|
||||
|
||||
/// The length, in bytes, of the match.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
/// Returns true if and only if this match is empty. That is, when
|
||||
/// `start() == end()`.
|
||||
///
|
||||
/// An empty match can only be returned when the empty string was among
|
||||
/// the patterns used to build the Aho-Corasick automaton.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn increment(&self, by: usize) -> Match {
|
||||
Match { pattern: self.pattern, len: self.len, end: self.end + by }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_span(id: usize, start: usize, end: usize) -> Match {
|
||||
Match { pattern: id, len: end - start, end }
|
||||
}
|
||||
}
|
||||
1214
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/nfa.rs
vendored
Normal file
1214
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/nfa.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
625
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/api.rs
vendored
Normal file
625
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/api.rs
vendored
Normal file
@@ -0,0 +1,625 @@
|
||||
use std::u16;
|
||||
|
||||
use crate::packed::pattern::Patterns;
|
||||
use crate::packed::rabinkarp::RabinKarp;
|
||||
use crate::packed::teddy::{self, Teddy};
|
||||
use crate::Match;
|
||||
|
||||
/// This is a limit placed on the total number of patterns we're willing to try
|
||||
/// and match at once. As more sophisticated algorithms are added, this number
|
||||
/// may be increased.
|
||||
const PATTERN_LIMIT: usize = 128;
|
||||
|
||||
/// A knob for controlling the match semantics of a packed multiple string
|
||||
/// searcher.
|
||||
///
|
||||
/// This differs from the
|
||||
/// [`MatchKind`](../enum.MatchKind.html)
|
||||
/// type in the top-level crate module in that it doesn't support
|
||||
/// "standard" match semantics, and instead only supports leftmost-first or
|
||||
/// leftmost-longest. Namely, "standard" semantics cannot be easily supported
|
||||
/// by packed searchers.
|
||||
///
|
||||
/// For more information on the distinction between leftmost-first and
|
||||
/// leftmost-longest, see the docs on the top-level `MatchKind` type.
|
||||
///
|
||||
/// Unlike the top-level `MatchKind` type, the default match semantics for this
|
||||
/// type are leftmost-first.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum MatchKind {
|
||||
/// Use leftmost-first match semantics, which reports leftmost matches.
|
||||
/// When there are multiple possible leftmost matches, the match
|
||||
/// corresponding to the pattern that appeared earlier when constructing
|
||||
/// the automaton is reported.
|
||||
///
|
||||
/// This is the default.
|
||||
LeftmostFirst,
|
||||
/// Use leftmost-longest match semantics, which reports leftmost matches.
|
||||
/// When there are multiple possible leftmost matches, the longest match
|
||||
/// is chosen.
|
||||
LeftmostLongest,
|
||||
/// Hints that destructuring should not be exhaustive.
|
||||
///
|
||||
/// This enum may grow additional variants, so this makes sure clients
|
||||
/// don't count on exhaustive matching. (Otherwise, adding a new variant
|
||||
/// could break existing code.)
|
||||
#[doc(hidden)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl Default for MatchKind {
|
||||
fn default() -> MatchKind {
|
||||
MatchKind::LeftmostFirst
|
||||
}
|
||||
}
|
||||
|
||||
/// The configuration for a packed multiple pattern searcher.
|
||||
///
|
||||
/// The configuration is currently limited only to being able to select the
|
||||
/// match semantics (leftmost-first or leftmost-longest) of a searcher. In the
|
||||
/// future, more knobs may be made available.
|
||||
///
|
||||
/// A configuration produces a [`packed::Builder`](struct.Builder.html), which
|
||||
/// in turn can be used to construct a
|
||||
/// [`packed::Searcher`](struct.Searcher.html) for searching.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example shows how to use leftmost-longest semantics instead of the
|
||||
/// default (leftmost-first).
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{Config, MatchKind};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Config::new()
|
||||
/// .match_kind(MatchKind::LeftmostLongest)
|
||||
/// .builder()
|
||||
/// .add("foo")
|
||||
/// .add("foobar")
|
||||
/// .build()?;
|
||||
/// let matches: Vec<usize> = searcher
|
||||
/// .find_iter("foobar")
|
||||
/// .map(|mat| mat.pattern())
|
||||
/// .collect();
|
||||
/// assert_eq!(vec![1], matches);
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Config {
|
||||
kind: MatchKind,
|
||||
force: Option<ForceAlgorithm>,
|
||||
force_teddy_fat: Option<bool>,
|
||||
force_avx: Option<bool>,
|
||||
}
|
||||
|
||||
/// An internal option for forcing the use of a particular packed algorithm.
|
||||
///
|
||||
/// When an algorithm is forced, if a searcher could not be constructed for it,
|
||||
/// then no searcher will be returned even if an alternative algorithm would
|
||||
/// work.
|
||||
#[derive(Clone, Debug)]
|
||||
enum ForceAlgorithm {
|
||||
Teddy,
|
||||
RabinKarp,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Create a new default configuration. A default configuration uses
|
||||
/// leftmost-first match semantics.
|
||||
pub fn new() -> Config {
|
||||
Config {
|
||||
kind: MatchKind::LeftmostFirst,
|
||||
force: None,
|
||||
force_teddy_fat: None,
|
||||
force_avx: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a packed builder from this configuration. The builder can be
|
||||
/// used to accumulate patterns and create a
|
||||
/// [`Searcher`](struct.Searcher.html)
|
||||
/// from them.
|
||||
pub fn builder(&self) -> Builder {
|
||||
Builder::from_config(self.clone())
|
||||
}
|
||||
|
||||
/// Set the match semantics for this configuration.
|
||||
pub fn match_kind(&mut self, kind: MatchKind) -> &mut Config {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
|
||||
/// An undocumented method for forcing the use of the Teddy algorithm.
|
||||
///
|
||||
/// This is only exposed for more precise testing and benchmarks. Callers
|
||||
/// should not use it as it is not part of the API stability guarantees of
|
||||
/// this crate.
|
||||
#[doc(hidden)]
|
||||
pub fn force_teddy(&mut self, yes: bool) -> &mut Config {
|
||||
if yes {
|
||||
self.force = Some(ForceAlgorithm::Teddy);
|
||||
} else {
|
||||
self.force = None;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// An undocumented method for forcing the use of the Fat Teddy algorithm.
|
||||
///
|
||||
/// This is only exposed for more precise testing and benchmarks. Callers
|
||||
/// should not use it as it is not part of the API stability guarantees of
|
||||
/// this crate.
|
||||
#[doc(hidden)]
|
||||
pub fn force_teddy_fat(&mut self, yes: Option<bool>) -> &mut Config {
|
||||
self.force_teddy_fat = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// An undocumented method for forcing the use of SSE (`Some(false)`) or
|
||||
/// AVX (`Some(true)`) algorithms.
|
||||
///
|
||||
/// This is only exposed for more precise testing and benchmarks. Callers
|
||||
/// should not use it as it is not part of the API stability guarantees of
|
||||
/// this crate.
|
||||
#[doc(hidden)]
|
||||
pub fn force_avx(&mut self, yes: Option<bool>) -> &mut Config {
|
||||
self.force_avx = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// An undocumented method for forcing the use of the Rabin-Karp algorithm.
|
||||
///
|
||||
/// This is only exposed for more precise testing and benchmarks. Callers
|
||||
/// should not use it as it is not part of the API stability guarantees of
|
||||
/// this crate.
|
||||
#[doc(hidden)]
|
||||
pub fn force_rabin_karp(&mut self, yes: bool) -> &mut Config {
|
||||
if yes {
|
||||
self.force = Some(ForceAlgorithm::RabinKarp);
|
||||
} else {
|
||||
self.force = None;
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for constructing a packed searcher from a collection of patterns.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example shows how to use a builder to construct a searcher. By
|
||||
/// default, leftmost-first match semantics are used.
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{Builder, MatchKind};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Builder::new()
|
||||
/// .add("foobar")
|
||||
/// .add("foo")
|
||||
/// .build()?;
|
||||
/// let matches: Vec<usize> = searcher
|
||||
/// .find_iter("foobar")
|
||||
/// .map(|mat| mat.pattern())
|
||||
/// .collect();
|
||||
/// assert_eq!(vec![0], matches);
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Builder {
|
||||
/// The configuration of this builder and subsequent matcher.
|
||||
config: Config,
|
||||
/// Set to true if the builder detects that a matcher cannot be built.
|
||||
inert: bool,
|
||||
/// The patterns provided by the caller.
|
||||
patterns: Patterns,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Create a new builder for constructing a multi-pattern searcher. This
|
||||
/// constructor uses the default configuration.
|
||||
pub fn new() -> Builder {
|
||||
Builder::from_config(Config::new())
|
||||
}
|
||||
|
||||
fn from_config(config: Config) -> Builder {
|
||||
Builder { config, inert: false, patterns: Patterns::new() }
|
||||
}
|
||||
|
||||
/// Build a searcher from the patterns added to this builder so far.
|
||||
pub fn build(&self) -> Option<Searcher> {
|
||||
if self.inert || self.patterns.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut patterns = self.patterns.clone();
|
||||
patterns.set_match_kind(self.config.kind);
|
||||
let rabinkarp = RabinKarp::new(&patterns);
|
||||
// Effectively, we only want to return a searcher if we can use Teddy,
|
||||
// since Teddy is our only fast packed searcher at the moment.
|
||||
// Rabin-Karp is only used when searching haystacks smaller than what
|
||||
// Teddy can support. Thus, the only way to get a Rabin-Karp searcher
|
||||
// is to force it using undocumented APIs (for tests/benchmarks).
|
||||
let (search_kind, minimum_len) = match self.config.force {
|
||||
None | Some(ForceAlgorithm::Teddy) => {
|
||||
let teddy = match self.build_teddy(&patterns) {
|
||||
None => return None,
|
||||
Some(teddy) => teddy,
|
||||
};
|
||||
let minimum_len = teddy.minimum_len();
|
||||
(SearchKind::Teddy(teddy), minimum_len)
|
||||
}
|
||||
Some(ForceAlgorithm::RabinKarp) => (SearchKind::RabinKarp, 0),
|
||||
};
|
||||
Some(Searcher { patterns, rabinkarp, search_kind, minimum_len })
|
||||
}
|
||||
|
||||
fn build_teddy(&self, patterns: &Patterns) -> Option<Teddy> {
|
||||
teddy::Builder::new()
|
||||
.avx(self.config.force_avx)
|
||||
.fat(self.config.force_teddy_fat)
|
||||
.build(&patterns)
|
||||
}
|
||||
|
||||
/// Add the given pattern to this set to match.
|
||||
///
|
||||
/// The order in which patterns are added is significant. Namely, when
|
||||
/// using leftmost-first match semantics, then when multiple patterns can
|
||||
/// match at a particular location, the pattern that was added first is
|
||||
/// used as the match.
|
||||
///
|
||||
/// If the number of patterns added exceeds the amount supported by packed
|
||||
/// searchers, then the builder will stop accumulating patterns and render
|
||||
/// itself inert. At this point, constructing a searcher will always return
|
||||
/// `None`.
|
||||
pub fn add<P: AsRef<[u8]>>(&mut self, pattern: P) -> &mut Builder {
|
||||
if self.inert {
|
||||
return self;
|
||||
} else if self.patterns.len() >= PATTERN_LIMIT {
|
||||
self.inert = true;
|
||||
self.patterns.reset();
|
||||
return self;
|
||||
}
|
||||
// Just in case PATTERN_LIMIT increases beyond u16::MAX.
|
||||
assert!(self.patterns.len() <= u16::MAX as usize);
|
||||
|
||||
let pattern = pattern.as_ref();
|
||||
if pattern.is_empty() {
|
||||
self.inert = true;
|
||||
self.patterns.reset();
|
||||
return self;
|
||||
}
|
||||
self.patterns.add(pattern);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add the given iterator of patterns to this set to match.
|
||||
///
|
||||
/// The iterator must yield elements that can be converted into a `&[u8]`.
|
||||
///
|
||||
/// The order in which patterns are added is significant. Namely, when
|
||||
/// using leftmost-first match semantics, then when multiple patterns can
|
||||
/// match at a particular location, the pattern that was added first is
|
||||
/// used as the match.
|
||||
///
|
||||
/// If the number of patterns added exceeds the amount supported by packed
|
||||
/// searchers, then the builder will stop accumulating patterns and render
|
||||
/// itself inert. At this point, constructing a searcher will always return
|
||||
/// `None`.
|
||||
pub fn extend<I, P>(&mut self, patterns: I) -> &mut Builder
|
||||
where
|
||||
I: IntoIterator<Item = P>,
|
||||
P: AsRef<[u8]>,
|
||||
{
|
||||
for p in patterns {
|
||||
self.add(p);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
fn default() -> Builder {
|
||||
Builder::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// A packed searcher for quickly finding occurrences of multiple patterns.
|
||||
///
|
||||
/// If callers need more flexible construction, or if one wants to change the
|
||||
/// match semantics (either leftmost-first or leftmost-longest), then one can
|
||||
/// use the [`Config`](struct.Config.html) and/or
|
||||
/// [`Builder`](struct.Builder.html) types for more fine grained control.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// This example shows how to create a searcher from an iterator of patterns.
|
||||
/// By default, leftmost-first match semantics are used.
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{MatchKind, Searcher};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
/// let matches: Vec<usize> = searcher
|
||||
/// .find_iter("foobar")
|
||||
/// .map(|mat| mat.pattern())
|
||||
/// .collect();
|
||||
/// assert_eq!(vec![0], matches);
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Searcher {
|
||||
patterns: Patterns,
|
||||
rabinkarp: RabinKarp,
|
||||
search_kind: SearchKind,
|
||||
minimum_len: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum SearchKind {
|
||||
Teddy(Teddy),
|
||||
RabinKarp,
|
||||
}
|
||||
|
||||
impl Searcher {
|
||||
/// A convenience function for constructing a searcher from an iterator
|
||||
/// of things that can be converted to a `&[u8]`.
|
||||
///
|
||||
/// If a searcher could not be constructed (either because of an
|
||||
/// unsupported CPU or because there are too many patterns), then `None`
|
||||
/// is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{MatchKind, Searcher};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
/// let matches: Vec<usize> = searcher
|
||||
/// .find_iter("foobar")
|
||||
/// .map(|mat| mat.pattern())
|
||||
/// .collect();
|
||||
/// assert_eq!(vec![0], matches);
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn new<I, P>(patterns: I) -> Option<Searcher>
|
||||
where
|
||||
I: IntoIterator<Item = P>,
|
||||
P: AsRef<[u8]>,
|
||||
{
|
||||
Builder::new().extend(patterns).build()
|
||||
}
|
||||
|
||||
/// Return the first occurrence of any of the patterns in this searcher,
|
||||
/// according to its match semantics, in the given haystack. The `Match`
|
||||
/// returned will include the identifier of the pattern that matched, which
|
||||
/// corresponds to the index of the pattern (starting from `0`) in which it
|
||||
/// was added.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{MatchKind, Searcher};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
/// let mat = searcher.find("foobar")?;
|
||||
/// assert_eq!(0, mat.pattern());
|
||||
/// assert_eq!(0, mat.start());
|
||||
/// assert_eq!(6, mat.end());
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<Match> {
|
||||
self.find_at(haystack, 0)
|
||||
}
|
||||
|
||||
/// Return the first occurrence of any of the patterns in this searcher,
|
||||
/// according to its match semantics, in the given haystack starting from
|
||||
/// the given position.
|
||||
///
|
||||
/// The `Match` returned will include the identifier of the pattern that
|
||||
/// matched, which corresponds to the index of the pattern (starting from
|
||||
/// `0`) in which it was added. The offsets in the `Match` will be relative
|
||||
/// to the start of `haystack` (and not `at`).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{MatchKind, Searcher};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
/// let mat = searcher.find_at("foofoobar", 3)?;
|
||||
/// assert_eq!(0, mat.pattern());
|
||||
/// assert_eq!(3, mat.start());
|
||||
/// assert_eq!(9, mat.end());
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn find_at<B: AsRef<[u8]>>(
|
||||
&self,
|
||||
haystack: B,
|
||||
at: usize,
|
||||
) -> Option<Match> {
|
||||
let haystack = haystack.as_ref();
|
||||
match self.search_kind {
|
||||
SearchKind::Teddy(ref teddy) => {
|
||||
if haystack[at..].len() < teddy.minimum_len() {
|
||||
return self.slow_at(haystack, at);
|
||||
}
|
||||
teddy.find_at(&self.patterns, haystack, at)
|
||||
}
|
||||
SearchKind::RabinKarp => {
|
||||
self.rabinkarp.find_at(&self.patterns, haystack, at)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return an iterator of non-overlapping occurrences of the patterns in
|
||||
/// this searcher, according to its match semantics, in the given haystack.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{MatchKind, Searcher};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
/// let matches: Vec<usize> = searcher
|
||||
/// .find_iter("foobar fooba foofoo")
|
||||
/// .map(|mat| mat.pattern())
|
||||
/// .collect();
|
||||
/// assert_eq!(vec![0, 1, 1, 1], matches);
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn find_iter<'a, 'b, B: ?Sized + AsRef<[u8]>>(
|
||||
&'a self,
|
||||
haystack: &'b B,
|
||||
) -> FindIter<'a, 'b> {
|
||||
FindIter { searcher: self, haystack: haystack.as_ref(), at: 0 }
|
||||
}
|
||||
|
||||
/// Returns the match kind used by this packed searcher.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use aho_corasick::packed::{MatchKind, Searcher};
|
||||
///
|
||||
/// # fn example() -> Option<()> {
|
||||
/// let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
/// // leftmost-first is the default.
|
||||
/// assert_eq!(&MatchKind::LeftmostFirst, searcher.match_kind());
|
||||
/// # Some(()) }
|
||||
/// # if cfg!(target_arch = "x86_64") {
|
||||
/// # example().unwrap()
|
||||
/// # } else {
|
||||
/// # assert!(example().is_none());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn match_kind(&self) -> &MatchKind {
|
||||
self.patterns.match_kind()
|
||||
}
|
||||
|
||||
/// Returns the minimum length of a haystack that is required in order for
|
||||
/// packed searching to be effective.
|
||||
///
|
||||
/// In some cases, the underlying packed searcher may not be able to search
|
||||
/// very short haystacks. When that occurs, the implementation will defer
|
||||
/// to a slower non-packed searcher (which is still generally faster than
|
||||
/// Aho-Corasick for a small number of patterns). However, callers may
|
||||
/// want to avoid ever using the slower variant, which one can do by
|
||||
/// never passing a haystack shorter than the minimum length returned by
|
||||
/// this method.
|
||||
pub fn minimum_len(&self) -> usize {
|
||||
self.minimum_len
|
||||
}
|
||||
|
||||
/// Returns the approximate total amount of heap used by this searcher, in
|
||||
/// units of bytes.
|
||||
pub fn heap_bytes(&self) -> usize {
|
||||
self.patterns.heap_bytes()
|
||||
+ self.rabinkarp.heap_bytes()
|
||||
+ self.search_kind.heap_bytes()
|
||||
}
|
||||
|
||||
/// Use a slow (non-packed) searcher.
|
||||
///
|
||||
/// This is useful when a packed searcher could be constructed, but could
|
||||
/// not be used to search a specific haystack. For example, if Teddy was
|
||||
/// built but the haystack is smaller than ~34 bytes, then Teddy might not
|
||||
/// be able to run.
|
||||
fn slow_at(&self, haystack: &[u8], at: usize) -> Option<Match> {
|
||||
self.rabinkarp.find_at(&self.patterns, haystack, at)
|
||||
}
|
||||
}
|
||||
|
||||
impl SearchKind {
|
||||
fn heap_bytes(&self) -> usize {
|
||||
match *self {
|
||||
SearchKind::Teddy(ref ted) => ted.heap_bytes(),
|
||||
SearchKind::RabinKarp => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over non-overlapping matches from a packed searcher.
|
||||
///
|
||||
/// The lifetime `'s` refers to the lifetime of the underlying
|
||||
/// [`Searcher`](struct.Searcher.html), while the lifetime `'h` refers to the
|
||||
/// lifetime of the haystack being searched.
|
||||
#[derive(Debug)]
|
||||
pub struct FindIter<'s, 'h> {
|
||||
searcher: &'s Searcher,
|
||||
haystack: &'h [u8],
|
||||
at: usize,
|
||||
}
|
||||
|
||||
impl<'s, 'h> Iterator for FindIter<'s, 'h> {
|
||||
type Item = Match;
|
||||
|
||||
fn next(&mut self) -> Option<Match> {
|
||||
if self.at > self.haystack.len() {
|
||||
return None;
|
||||
}
|
||||
match self.searcher.find_at(&self.haystack, self.at) {
|
||||
None => None,
|
||||
Some(c) => {
|
||||
self.at = c.end;
|
||||
Some(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/mod.rs
vendored
Normal file
117
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/mod.rs
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*!
|
||||
A lower level API for packed multiple substring search, principally for a small
|
||||
number of patterns.
|
||||
|
||||
This sub-module provides vectorized routines for quickly finding matches of a
|
||||
small number of patterns. In general, users of this crate shouldn't need to
|
||||
interface with this module directly, as the primary
|
||||
[`AhoCorasick`](../struct.AhoCorasick.html)
|
||||
searcher will use these routines automatically as a prefilter when applicable.
|
||||
However, in some cases, callers may want to bypass the Aho-Corasick machinery
|
||||
entirely and use this vectorized searcher directly.
|
||||
|
||||
# Overview
|
||||
|
||||
The primary types in this sub-module are:
|
||||
|
||||
* [`Searcher`](struct.Searcher.html) executes the actual search algorithm to
|
||||
report matches in a haystack.
|
||||
* [`Builder`](struct.Builder.html) accumulates patterns incrementally and can
|
||||
construct a `Searcher`.
|
||||
* [`Config`](struct.Config.html) permits tuning the searcher, and itself will
|
||||
produce a `Builder` (which can then be used to build a `Searcher`).
|
||||
Currently, the only tuneable knob are the match semantics, but this may be
|
||||
expanded in the future.
|
||||
|
||||
# Examples
|
||||
|
||||
This example shows how to create a searcher from an iterator of patterns.
|
||||
By default, leftmost-first match semantics are used. (See the top-level
|
||||
[`MatchKind`](../enum.MatchKind.html) type for more details about match
|
||||
semantics, which apply similarly to packed substring search.)
|
||||
|
||||
```
|
||||
use aho_corasick::packed::{MatchKind, Searcher};
|
||||
|
||||
# fn example() -> Option<()> {
|
||||
let searcher = Searcher::new(["foobar", "foo"].iter().cloned())?;
|
||||
let matches: Vec<usize> = searcher
|
||||
.find_iter("foobar")
|
||||
.map(|mat| mat.pattern())
|
||||
.collect();
|
||||
assert_eq!(vec![0], matches);
|
||||
# Some(()) }
|
||||
# if cfg!(target_arch = "x86_64") {
|
||||
# example().unwrap()
|
||||
# } else {
|
||||
# assert!(example().is_none());
|
||||
# }
|
||||
```
|
||||
|
||||
This example shows how to use [`Config`](struct.Config.html) to change the
|
||||
match semantics to leftmost-longest:
|
||||
|
||||
```
|
||||
use aho_corasick::packed::{Config, MatchKind};
|
||||
|
||||
# fn example() -> Option<()> {
|
||||
let searcher = Config::new()
|
||||
.match_kind(MatchKind::LeftmostLongest)
|
||||
.builder()
|
||||
.add("foo")
|
||||
.add("foobar")
|
||||
.build()?;
|
||||
let matches: Vec<usize> = searcher
|
||||
.find_iter("foobar")
|
||||
.map(|mat| mat.pattern())
|
||||
.collect();
|
||||
assert_eq!(vec![1], matches);
|
||||
# Some(()) }
|
||||
# if cfg!(target_arch = "x86_64") {
|
||||
# example().unwrap()
|
||||
# } else {
|
||||
# assert!(example().is_none());
|
||||
# }
|
||||
```
|
||||
|
||||
# Packed substring searching
|
||||
|
||||
Packed substring searching refers to the use of SIMD (Single Instruction,
|
||||
Multiple Data) to accelerate the detection of matches in a haystack. Unlike
|
||||
conventional algorithms, such as Aho-Corasick, SIMD algorithms for substring
|
||||
search tend to do better with a small number of patterns, where as Aho-Corasick
|
||||
generally maintains reasonably consistent performance regardless of the number
|
||||
of patterns you give it. Because of this, the vectorized searcher in this
|
||||
sub-module cannot be used as a general purpose searcher, since building the
|
||||
searcher may fail. However, in exchange, when searching for a small number of
|
||||
patterns, searching can be quite a bit faster than Aho-Corasick (sometimes by
|
||||
an order of magnitude).
|
||||
|
||||
The key take away here is that constructing a searcher from a list of patterns
|
||||
is a fallible operation. While the precise conditions under which building a
|
||||
searcher can fail is specifically an implementation detail, here are some
|
||||
common reasons:
|
||||
|
||||
* Too many patterns were given. Typically, the limit is on the order of 100 or
|
||||
so, but this limit may fluctuate based on available CPU features.
|
||||
* The available packed algorithms require CPU features that aren't available.
|
||||
For example, currently, this crate only provides packed algorithms for
|
||||
`x86_64`. Therefore, constructing a packed searcher on any other target
|
||||
(e.g., ARM) will always fail.
|
||||
* Zero patterns were given, or one of the patterns given was empty. Packed
|
||||
searchers require at least one pattern and that all patterns are non-empty.
|
||||
* Something else about the nature of the patterns (typically based on
|
||||
heuristics) suggests that a packed searcher would perform very poorly, so
|
||||
no searcher is built.
|
||||
*/
|
||||
|
||||
pub use crate::packed::api::{Builder, Config, FindIter, MatchKind, Searcher};
|
||||
|
||||
mod api;
|
||||
mod pattern;
|
||||
mod rabinkarp;
|
||||
mod teddy;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod vector;
|
||||
318
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/pattern.rs
vendored
Normal file
318
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/pattern.rs
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::u16;
|
||||
use std::usize;
|
||||
|
||||
use crate::packed::api::MatchKind;
|
||||
|
||||
/// The type used for representing a pattern identifier.
|
||||
///
|
||||
/// We don't use `usize` here because our packed searchers don't scale to
|
||||
/// huge numbers of patterns, so we keep things a bit smaller.
|
||||
pub type PatternID = u16;
|
||||
|
||||
/// A non-empty collection of non-empty patterns to search for.
|
||||
///
|
||||
/// This collection of patterns is what is passed around to both execute
|
||||
/// searches and to construct the searchers themselves. Namely, this permits
|
||||
/// searches to avoid copying all of the patterns, and allows us to keep only
|
||||
/// one copy throughout all packed searchers.
|
||||
///
|
||||
/// Note that this collection is not a set. The same pattern can appear more
|
||||
/// than once.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Patterns {
|
||||
/// The match semantics supported by this collection of patterns.
|
||||
///
|
||||
/// The match semantics determines the order of the iterator over patterns.
|
||||
/// For leftmost-first, patterns are provided in the same order as were
|
||||
/// provided by the caller. For leftmost-longest, patterns are provided in
|
||||
/// descending order of length, with ties broken by the order in which they
|
||||
/// were provided by the caller.
|
||||
kind: MatchKind,
|
||||
/// The collection of patterns, indexed by their identifier.
|
||||
by_id: Vec<Vec<u8>>,
|
||||
/// The order of patterns defined for iteration, given by pattern
|
||||
/// identifiers. The order of `by_id` and `order` is always the same for
|
||||
/// leftmost-first semantics, but may be different for leftmost-longest
|
||||
/// semantics.
|
||||
order: Vec<PatternID>,
|
||||
/// The length of the smallest pattern, in bytes.
|
||||
minimum_len: usize,
|
||||
/// The largest pattern identifier. This should always be equivalent to
|
||||
/// the number of patterns minus one in this collection.
|
||||
max_pattern_id: PatternID,
|
||||
/// The total number of pattern bytes across the entire collection. This
|
||||
/// is used for reporting total heap usage in constant time.
|
||||
total_pattern_bytes: usize,
|
||||
}
|
||||
|
||||
impl Patterns {
|
||||
/// Create a new collection of patterns for the given match semantics. The
|
||||
/// ID of each pattern is the index of the pattern at which it occurs in
|
||||
/// the `by_id` slice.
|
||||
///
|
||||
/// If any of the patterns in the slice given are empty, then this panics.
|
||||
/// Similarly, if the number of patterns given is zero, then this also
|
||||
/// panics.
|
||||
pub fn new() -> Patterns {
|
||||
Patterns {
|
||||
kind: MatchKind::default(),
|
||||
by_id: vec![],
|
||||
order: vec![],
|
||||
minimum_len: usize::MAX,
|
||||
max_pattern_id: 0,
|
||||
total_pattern_bytes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a pattern to this collection.
|
||||
///
|
||||
/// This panics if the pattern given is empty.
|
||||
pub fn add(&mut self, bytes: &[u8]) {
|
||||
assert!(!bytes.is_empty());
|
||||
assert!(self.by_id.len() <= u16::MAX as usize);
|
||||
|
||||
let id = self.by_id.len() as u16;
|
||||
self.max_pattern_id = id;
|
||||
self.order.push(id);
|
||||
self.by_id.push(bytes.to_vec());
|
||||
self.minimum_len = cmp::min(self.minimum_len, bytes.len());
|
||||
self.total_pattern_bytes += bytes.len();
|
||||
}
|
||||
|
||||
/// Set the match kind semantics for this collection of patterns.
|
||||
///
|
||||
/// If the kind is not set, then the default is leftmost-first.
|
||||
pub fn set_match_kind(&mut self, kind: MatchKind) {
|
||||
match kind {
|
||||
MatchKind::LeftmostFirst => {
|
||||
self.order.sort();
|
||||
}
|
||||
MatchKind::LeftmostLongest => {
|
||||
let (order, by_id) = (&mut self.order, &mut self.by_id);
|
||||
order.sort_by(|&id1, &id2| {
|
||||
by_id[id1 as usize]
|
||||
.len()
|
||||
.cmp(&by_id[id2 as usize].len())
|
||||
.reverse()
|
||||
});
|
||||
}
|
||||
MatchKind::__Nonexhaustive => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the number of patterns in this collection.
|
||||
///
|
||||
/// This is guaranteed to be greater than zero.
|
||||
pub fn len(&self) -> usize {
|
||||
self.by_id.len()
|
||||
}
|
||||
|
||||
/// Returns true if and only if this collection of patterns is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Returns the approximate total amount of heap used by these patterns, in
|
||||
/// units of bytes.
|
||||
pub fn heap_bytes(&self) -> usize {
|
||||
self.order.len() * mem::size_of::<PatternID>()
|
||||
+ self.by_id.len() * mem::size_of::<Vec<u8>>()
|
||||
+ self.total_pattern_bytes
|
||||
}
|
||||
|
||||
/// Clears all heap memory associated with this collection of patterns and
|
||||
/// resets all state such that it is a valid empty collection.
|
||||
pub fn reset(&mut self) {
|
||||
self.kind = MatchKind::default();
|
||||
self.by_id.clear();
|
||||
self.order.clear();
|
||||
self.minimum_len = usize::MAX;
|
||||
self.max_pattern_id = 0;
|
||||
}
|
||||
|
||||
/// Return the maximum pattern identifier in this collection. This can be
|
||||
/// useful in searchers for ensuring that the collection of patterns they
|
||||
/// are provided at search time and at build time have the same size.
|
||||
pub fn max_pattern_id(&self) -> PatternID {
|
||||
assert_eq!((self.max_pattern_id + 1) as usize, self.len());
|
||||
self.max_pattern_id
|
||||
}
|
||||
|
||||
/// Returns the length, in bytes, of the smallest pattern.
|
||||
///
|
||||
/// This is guaranteed to be at least one.
|
||||
pub fn minimum_len(&self) -> usize {
|
||||
self.minimum_len
|
||||
}
|
||||
|
||||
/// Returns the match semantics used by these patterns.
|
||||
pub fn match_kind(&self) -> &MatchKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
/// Return the pattern with the given identifier. If such a pattern does
|
||||
/// not exist, then this panics.
|
||||
pub fn get(&self, id: PatternID) -> Pattern<'_> {
|
||||
Pattern(&self.by_id[id as usize])
|
||||
}
|
||||
|
||||
/// Return the pattern with the given identifier without performing bounds
|
||||
/// checks.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Callers must ensure that a pattern with the given identifier exists
|
||||
/// before using this method.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub unsafe fn get_unchecked(&self, id: PatternID) -> Pattern<'_> {
|
||||
Pattern(self.by_id.get_unchecked(id as usize))
|
||||
}
|
||||
|
||||
/// Return an iterator over all the patterns in this collection, in the
|
||||
/// order in which they should be matched.
|
||||
///
|
||||
/// Specifically, in a naive multi-pattern matcher, the following is
|
||||
/// guaranteed to satisfy the match semantics of this collection of
|
||||
/// patterns:
|
||||
///
|
||||
/// ```ignore
|
||||
/// for i in 0..haystack.len():
|
||||
/// for p in patterns.iter():
|
||||
/// if haystack[i..].starts_with(p.bytes()):
|
||||
/// return Match(p.id(), i, i + p.bytes().len())
|
||||
/// ```
|
||||
///
|
||||
/// Namely, among the patterns in a collection, if they are matched in
|
||||
/// the order provided by this iterator, then the result is guaranteed
|
||||
/// to satisfy the correct match semantics. (Either leftmost-first or
|
||||
/// leftmost-longest.)
|
||||
pub fn iter(&self) -> PatternIter<'_> {
|
||||
PatternIter { patterns: self, i: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the patterns in the `Patterns` collection.
|
||||
///
|
||||
/// The order of the patterns provided by this iterator is consistent with the
|
||||
/// match semantics of the originating collection of patterns.
|
||||
///
|
||||
/// The lifetime `'p` corresponds to the lifetime of the collection of patterns
|
||||
/// this is iterating over.
|
||||
#[derive(Debug)]
|
||||
pub struct PatternIter<'p> {
|
||||
patterns: &'p Patterns,
|
||||
i: usize,
|
||||
}
|
||||
|
||||
impl<'p> Iterator for PatternIter<'p> {
|
||||
type Item = (PatternID, Pattern<'p>);
|
||||
|
||||
fn next(&mut self) -> Option<(PatternID, Pattern<'p>)> {
|
||||
if self.i >= self.patterns.len() {
|
||||
return None;
|
||||
}
|
||||
let id = self.patterns.order[self.i];
|
||||
let p = self.patterns.get(id);
|
||||
self.i += 1;
|
||||
Some((id, p))
|
||||
}
|
||||
}
|
||||
|
||||
/// A pattern that is used in packed searching.
|
||||
#[derive(Clone)]
|
||||
pub struct Pattern<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> fmt::Debug for Pattern<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Pattern")
|
||||
.field("lit", &String::from_utf8_lossy(&self.0))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Pattern<'p> {
|
||||
/// Returns the length of this pattern, in bytes.
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
/// Returns the bytes of this pattern.
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Returns the first `len` low nybbles from this pattern. If this pattern
|
||||
/// is shorter than `len`, then this panics.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub fn low_nybbles(&self, len: usize) -> Vec<u8> {
|
||||
let mut nybs = vec![];
|
||||
for &b in self.bytes().iter().take(len) {
|
||||
nybs.push(b & 0xF);
|
||||
}
|
||||
nybs
|
||||
}
|
||||
|
||||
/// Returns true if this pattern is a prefix of the given bytes.
|
||||
#[inline(always)]
|
||||
pub fn is_prefix(&self, bytes: &[u8]) -> bool {
|
||||
self.len() <= bytes.len() && self.equals(&bytes[..self.len()])
|
||||
}
|
||||
|
||||
/// Returns true if and only if this pattern equals the given bytes.
|
||||
#[inline(always)]
|
||||
pub fn equals(&self, bytes: &[u8]) -> bool {
|
||||
// Why not just use memcmp for this? Well, memcmp requires calling out
|
||||
// to libc, and this routine is called in fairly hot code paths. Other
|
||||
// than just calling out to libc, it also seems to result in worse
|
||||
// codegen. By rolling our own memcpy in pure Rust, it seems to appear
|
||||
// more friendly to the optimizer.
|
||||
//
|
||||
// This results in an improvement in just about every benchmark. Some
|
||||
// smaller than others, but in some cases, up to 30% faster.
|
||||
|
||||
if self.len() != bytes.len() {
|
||||
return false;
|
||||
}
|
||||
if self.len() < 8 {
|
||||
for (&b1, &b2) in self.bytes().iter().zip(bytes) {
|
||||
if b1 != b2 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// When we have 8 or more bytes to compare, then proceed in chunks of
|
||||
// 8 at a time using unaligned loads.
|
||||
let mut p1 = self.bytes().as_ptr();
|
||||
let mut p2 = bytes.as_ptr();
|
||||
let p1end = self.bytes()[self.len() - 8..].as_ptr();
|
||||
let p2end = bytes[bytes.len() - 8..].as_ptr();
|
||||
// SAFETY: Via the conditional above, we know that both `p1` and `p2`
|
||||
// have the same length, so `p1 < p1end` implies that `p2 < p2end`.
|
||||
// Thus, derefencing both `p1` and `p2` in the loop below is safe.
|
||||
//
|
||||
// Moreover, we set `p1end` and `p2end` to be 8 bytes before the actual
|
||||
// end of of `p1` and `p2`. Thus, the final dereference outside of the
|
||||
// loop is guaranteed to be valid.
|
||||
//
|
||||
// Finally, we needn't worry about 64-bit alignment here, since we
|
||||
// do unaligned loads.
|
||||
unsafe {
|
||||
while p1 < p1end {
|
||||
let v1 = (p1 as *const u64).read_unaligned();
|
||||
let v2 = (p2 as *const u64).read_unaligned();
|
||||
if v1 != v2 {
|
||||
return false;
|
||||
}
|
||||
p1 = p1.add(8);
|
||||
p2 = p2.add(8);
|
||||
}
|
||||
let v1 = (p1end as *const u64).read_unaligned();
|
||||
let v2 = (p2end as *const u64).read_unaligned();
|
||||
v1 == v2
|
||||
}
|
||||
}
|
||||
}
|
||||
185
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/rabinkarp.rs
vendored
Normal file
185
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/rabinkarp.rs
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
use std::mem;
|
||||
|
||||
use crate::packed::pattern::{PatternID, Patterns};
|
||||
use crate::Match;
|
||||
|
||||
/// The type of the rolling hash used in the Rabin-Karp algorithm.
|
||||
type Hash = usize;
|
||||
|
||||
/// The number of buckets to store our patterns in. We don't want this to be
|
||||
/// too big in order to avoid wasting memory, but we don't want it to be too
|
||||
/// small either to avoid spending too much time confirming literals.
|
||||
///
|
||||
/// The number of buckets MUST be a power of two. Otherwise, determining the
|
||||
/// bucket from a hash will slow down the code considerably. Using a power
|
||||
/// of two means `hash % NUM_BUCKETS` can compile down to a simple `and`
|
||||
/// instruction.
|
||||
const NUM_BUCKETS: usize = 64;
|
||||
|
||||
/// An implementation of the Rabin-Karp algorithm. The main idea of this
|
||||
/// algorithm is to maintain a rolling hash as it moves through the input, and
|
||||
/// then check whether that hash corresponds to the same hash for any of the
|
||||
/// patterns we're looking for.
|
||||
///
|
||||
/// A draw back of naively scaling Rabin-Karp to multiple patterns is that
|
||||
/// it requires all of the patterns to be the same length, which in turn
|
||||
/// corresponds to the number of bytes to hash. We adapt this to work for
|
||||
/// multiple patterns of varying size by fixing the number of bytes to hash
|
||||
/// to be the length of the smallest pattern. We also split the patterns into
|
||||
/// several buckets to hopefully make the confirmation step faster.
|
||||
///
|
||||
/// Wikipedia has a decent explanation, if a bit heavy on the theory:
|
||||
/// https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
|
||||
///
|
||||
/// But ESMAJ provides something a bit more concrete:
|
||||
/// https://www-igm.univ-mlv.fr/~lecroq/string/node5.html
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RabinKarp {
|
||||
/// The order of patterns in each bucket is significant. Namely, they are
|
||||
/// arranged such that the first one to match is the correct match. This
|
||||
/// may not necessarily correspond to the order provided by the caller.
|
||||
/// For example, if leftmost-longest semantics are used, then the patterns
|
||||
/// are sorted by their length in descending order. If leftmost-first
|
||||
/// semantics are used, then the patterns are sorted by their pattern ID
|
||||
/// in ascending order (which corresponds to the caller's order).
|
||||
buckets: Vec<Vec<(Hash, PatternID)>>,
|
||||
/// The length of the hashing window. Generally, this corresponds to the
|
||||
/// length of the smallest pattern.
|
||||
hash_len: usize,
|
||||
/// The factor to subtract out of a hash before updating it with a new
|
||||
/// byte.
|
||||
hash_2pow: usize,
|
||||
/// The maximum identifier of a pattern. This is used as a sanity check
|
||||
/// to ensure that the patterns provided by the caller are the same as
|
||||
/// the patterns that were used to compile the matcher. This sanity check
|
||||
/// possibly permits safely eliminating bounds checks regardless of what
|
||||
/// patterns are provided by the caller.
|
||||
///
|
||||
/// (Currently, we don't use this to elide bounds checks since it doesn't
|
||||
/// result in a measurable performance improvement, but we do use it for
|
||||
/// better failure modes.)
|
||||
max_pattern_id: PatternID,
|
||||
}
|
||||
|
||||
impl RabinKarp {
|
||||
/// Compile a new Rabin-Karp matcher from the patterns given.
|
||||
///
|
||||
/// This panics if any of the patterns in the collection are empty, or if
|
||||
/// the collection is itself empty.
|
||||
pub fn new(patterns: &Patterns) -> RabinKarp {
|
||||
assert!(patterns.len() >= 1);
|
||||
let hash_len = patterns.minimum_len();
|
||||
assert!(hash_len >= 1);
|
||||
|
||||
let mut hash_2pow = 1usize;
|
||||
for _ in 1..hash_len {
|
||||
hash_2pow = hash_2pow.wrapping_shl(1);
|
||||
}
|
||||
|
||||
let mut rk = RabinKarp {
|
||||
buckets: vec![vec![]; NUM_BUCKETS],
|
||||
hash_len,
|
||||
hash_2pow,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
};
|
||||
for (id, pat) in patterns.iter() {
|
||||
let hash = rk.hash(&pat.bytes()[..rk.hash_len]);
|
||||
let bucket = hash % NUM_BUCKETS;
|
||||
rk.buckets[bucket].push((hash, id));
|
||||
}
|
||||
rk
|
||||
}
|
||||
|
||||
/// Return the first matching pattern in the given haystack, begining the
|
||||
/// search at `at`.
|
||||
pub fn find_at(
|
||||
&self,
|
||||
patterns: &Patterns,
|
||||
haystack: &[u8],
|
||||
mut at: usize,
|
||||
) -> Option<Match> {
|
||||
assert_eq!(NUM_BUCKETS, self.buckets.len());
|
||||
assert_eq!(
|
||||
self.max_pattern_id,
|
||||
patterns.max_pattern_id(),
|
||||
"Rabin-Karp must be called with same patterns it was built with",
|
||||
);
|
||||
|
||||
if at + self.hash_len > haystack.len() {
|
||||
return None;
|
||||
}
|
||||
let mut hash = self.hash(&haystack[at..at + self.hash_len]);
|
||||
loop {
|
||||
let bucket = &self.buckets[hash % NUM_BUCKETS];
|
||||
for &(phash, pid) in bucket {
|
||||
if phash == hash {
|
||||
if let Some(c) = self.verify(patterns, pid, haystack, at) {
|
||||
return Some(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
if at + self.hash_len >= haystack.len() {
|
||||
return None;
|
||||
}
|
||||
hash = self.update_hash(
|
||||
hash,
|
||||
haystack[at],
|
||||
haystack[at + self.hash_len],
|
||||
);
|
||||
at += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the approximate total amount of heap used by this searcher, in
|
||||
/// units of bytes.
|
||||
pub fn heap_bytes(&self) -> usize {
|
||||
let num_patterns = self.max_pattern_id as usize + 1;
|
||||
self.buckets.len() * mem::size_of::<Vec<(Hash, PatternID)>>()
|
||||
+ num_patterns * mem::size_of::<(Hash, PatternID)>()
|
||||
}
|
||||
|
||||
/// Verify whether the pattern with the given id matches at
|
||||
/// `haystack[at..]`.
|
||||
///
|
||||
/// We tag this function as `cold` because it helps improve codegen.
|
||||
/// Intuitively, it would seem like inlining it would be better. However,
|
||||
/// the only time this is called and a match is not found is when there
|
||||
/// there is a hash collision, or when a prefix of a pattern matches but
|
||||
/// the entire pattern doesn't match. This is hopefully fairly rare, and
|
||||
/// if it does occur a lot, it's going to be slow no matter what we do.
|
||||
#[cold]
|
||||
fn verify(
|
||||
&self,
|
||||
patterns: &Patterns,
|
||||
id: PatternID,
|
||||
haystack: &[u8],
|
||||
at: usize,
|
||||
) -> Option<Match> {
|
||||
let pat = patterns.get(id);
|
||||
if pat.is_prefix(&haystack[at..]) {
|
||||
Some(Match::from_span(id as usize, at, at + pat.len()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Hash the given bytes.
|
||||
fn hash(&self, bytes: &[u8]) -> Hash {
|
||||
assert_eq!(self.hash_len, bytes.len());
|
||||
|
||||
let mut hash = 0usize;
|
||||
for &b in bytes {
|
||||
hash = hash.wrapping_shl(1).wrapping_add(b as usize);
|
||||
}
|
||||
hash
|
||||
}
|
||||
|
||||
/// Update the hash given based on removing `old_byte` at the beginning
|
||||
/// of some byte string, and appending `new_byte` to the end of that same
|
||||
/// byte string.
|
||||
fn update_hash(&self, prev: Hash, old_byte: u8, new_byte: u8) -> Hash {
|
||||
prev.wrapping_sub((old_byte as usize).wrapping_mul(self.hash_2pow))
|
||||
.wrapping_shl(1)
|
||||
.wrapping_add(new_byte as usize)
|
||||
}
|
||||
}
|
||||
386
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/README.md
vendored
Normal file
386
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/README.md
vendored
Normal file
@@ -0,0 +1,386 @@
|
||||
Teddy is a SIMD accelerated multiple substring matching algorithm. The name
|
||||
and the core ideas in the algorithm were learned from the [Hyperscan][1_u]
|
||||
project. The implementation in this repository was mostly motivated for use in
|
||||
accelerating regex searches by searching for small sets of required literals
|
||||
extracted from the regex.
|
||||
|
||||
|
||||
# Background
|
||||
|
||||
The key idea of Teddy is to do *packed* substring matching. In the literature,
|
||||
packed substring matching is the idea of examining multiple bytes in a haystack
|
||||
at a time to detect matches. Implementations of, for example, memchr (which
|
||||
detects matches of a single byte) have been doing this for years. Only
|
||||
recently, with the introduction of various SIMD instructions, has this been
|
||||
extended to substring matching. The PCMPESTRI instruction (and its relatives),
|
||||
for example, implements substring matching in hardware. It is, however, limited
|
||||
to substrings of length 16 bytes or fewer, but this restriction is fine in a
|
||||
regex engine, since we rarely care about the performance difference between
|
||||
searching for a 16 byte literal and a 16 + N literal; 16 is already long
|
||||
enough. The key downside of the PCMPESTRI instruction, on current (2016) CPUs
|
||||
at least, is its latency and throughput. As a result, it is often faster to
|
||||
do substring search with a Boyer-Moore (or Two-Way) variant and a well placed
|
||||
memchr to quickly skip through the haystack.
|
||||
|
||||
There are fewer results from the literature on packed substring matching,
|
||||
and even fewer for packed multiple substring matching. Ben-Kiki et al. [2]
|
||||
describes use of PCMPESTRI for substring matching, but is mostly theoretical
|
||||
and hand-waves performance. There is other theoretical work done by Bille [3]
|
||||
as well.
|
||||
|
||||
The rest of the work in the field, as far as I'm aware, is by Faro and Kulekci
|
||||
and is generally focused on multiple pattern search. Their first paper [4a]
|
||||
introduces the concept of a fingerprint, which is computed for every block of
|
||||
N bytes in every pattern. The haystack is then scanned N bytes at a time and
|
||||
a fingerprint is computed in the same way it was computed for blocks in the
|
||||
patterns. If the fingerprint corresponds to one that was found in a pattern,
|
||||
then a verification step follows to confirm that one of the substrings with the
|
||||
corresponding fingerprint actually matches at the current location. Various
|
||||
implementation tricks are employed to make sure the fingerprint lookup is fast;
|
||||
typically by truncating the fingerprint. (This may, of course, provoke more
|
||||
steps in the verification process, so a balance must be struck.)
|
||||
|
||||
The main downside of [4a] is that the minimum substring length is 32 bytes,
|
||||
presumably because of how the algorithm uses certain SIMD instructions. This
|
||||
essentially makes it useless for general purpose regex matching, where a small
|
||||
number of short patterns is far more likely.
|
||||
|
||||
Faro and Kulekci published another paper [4b] that is conceptually very similar
|
||||
to [4a]. The key difference is that it uses the CRC32 instruction (introduced
|
||||
as part of SSE 4.2) to compute fingerprint values. This also enables the
|
||||
algorithm to work effectively on substrings as short as 7 bytes with 4 byte
|
||||
windows. 7 bytes is unfortunately still too long. The window could be
|
||||
technically shrunk to 2 bytes, thereby reducing minimum length to 3, but the
|
||||
small window size ends up negating most performance benefits—and it's likely
|
||||
the common case in a general purpose regex engine.
|
||||
|
||||
Faro and Kulekci also published [4c] that appears to be intended as a
|
||||
replacement to using PCMPESTRI. In particular, it is specifically motivated by
|
||||
the high throughput/latency time of PCMPESTRI and therefore chooses other SIMD
|
||||
instructions that are faster. While this approach works for short substrings,
|
||||
I personally couldn't see a way to generalize it to multiple substring search.
|
||||
|
||||
Faro and Kulekci have another paper [4d] that I haven't been able to read
|
||||
because it is behind a paywall.
|
||||
|
||||
|
||||
# Teddy
|
||||
|
||||
Finally, we get to Teddy. If the above literature review is complete, then it
|
||||
appears that Teddy is a novel algorithm. More than that, in my experience, it
|
||||
completely blows away the competition for short substrings, which is exactly
|
||||
what we want in a general purpose regex engine. Again, the algorithm appears
|
||||
to be developed by the authors of [Hyperscan][1_u]. Hyperscan was open sourced
|
||||
late 2015, and no earlier history could be found. Therefore, tracking the exact
|
||||
provenance of the algorithm with respect to the published literature seems
|
||||
difficult.
|
||||
|
||||
At a high level, Teddy works somewhat similarly to the fingerprint algorithms
|
||||
published by Faro and Kulekci, but Teddy does it in a way that scales a bit
|
||||
better. Namely:
|
||||
|
||||
1. Teddy's core algorithm scans the haystack in 16 (for SSE, or 32 for AVX)
|
||||
byte chunks. 16 (or 32) is significant because it corresponds to the number
|
||||
of bytes in a SIMD vector.
|
||||
2. Bitwise operations are performed on each chunk to discover if any region of
|
||||
it matches a set of precomputed fingerprints from the patterns. If there are
|
||||
matches, then a verification step is performed. In this implementation, our
|
||||
verification step is naive. This can be improved upon.
|
||||
|
||||
The details to make this work are quite clever. First, we must choose how to
|
||||
pick our fingerprints. In Hyperscan's implementation, I *believe* they use the
|
||||
last N bytes of each substring, where N must be at least the minimum length of
|
||||
any substring in the set being searched. In this implementation, we use the
|
||||
first N bytes of each substring. (The tradeoffs between these choices aren't
|
||||
yet clear to me.) We then must figure out how to quickly test whether an
|
||||
occurrence of any fingerprint from the set of patterns appears in a 16 byte
|
||||
block from the haystack. To keep things simple, let's assume N = 1 and examine
|
||||
some examples to motivate the approach. Here are our patterns:
|
||||
|
||||
```ignore
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
```
|
||||
|
||||
The corresponding fingerprints, for N = 1, are `f`, `b` and `b`. Now let's set
|
||||
our 16 byte block to:
|
||||
|
||||
```ignore
|
||||
bat cat foo bump
|
||||
xxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
To cut to the chase, Teddy works by using bitsets. In particular, Teddy creates
|
||||
a mask that allows us to quickly compute membership of a fingerprint in a 16
|
||||
byte block that also tells which pattern the fingerprint corresponds to. In
|
||||
this case, our fingerprint is a single byte, so an appropriate abstraction is
|
||||
a map from a single byte to a list of patterns that contain that fingerprint:
|
||||
|
||||
```ignore
|
||||
f |--> foo
|
||||
b |--> bar, baz
|
||||
```
|
||||
|
||||
Now, all we need to do is figure out how to represent this map in vector space
|
||||
and use normal SIMD operations to perform a lookup. The first simplification
|
||||
we can make is to represent our patterns as bit fields occupying a single
|
||||
byte. This is important, because a single SIMD vector can store 16 bytes.
|
||||
|
||||
```ignore
|
||||
f |--> 00000001
|
||||
b |--> 00000010, 00000100
|
||||
```
|
||||
|
||||
How do we perform lookup though? It turns out that SSSE3 introduced a very cool
|
||||
instruction called PSHUFB. The instruction takes two SIMD vectors, `A` and `B`,
|
||||
and returns a third vector `C`. All vectors are treated as 16 8-bit integers.
|
||||
`C` is formed by `C[i] = A[B[i]]`. (This is a bit of a simplification, but true
|
||||
for the purposes of this algorithm. For full details, see [Intel's Intrinsics
|
||||
Guide][5_u].) This essentially lets us use the values in `B` to lookup values
|
||||
in `A`.
|
||||
|
||||
If we could somehow cause `B` to contain our 16 byte block from the haystack,
|
||||
and if `A` could contain our bitmasks, then we'd end up with something like
|
||||
this for `A`:
|
||||
|
||||
```ignore
|
||||
0x00 0x01 ... 0x62 ... 0x66 ... 0xFF
|
||||
A = 0 0 00000110 00000001 0
|
||||
```
|
||||
|
||||
And if `B` contains our window from our haystack, we could use shuffle to take
|
||||
the values from `B` and use them to look up our bitsets in `A`. But of course,
|
||||
we can't do this because `A` in the above example contains 256 bytes, which
|
||||
is much larger than the size of a SIMD vector.
|
||||
|
||||
Nybbles to the rescue! A nybble is 4 bits. Instead of one mask to hold all of
|
||||
our bitsets, we can use two masks, where one mask corresponds to the lower four
|
||||
bits of our fingerprint and the other mask corresponds to the upper four bits.
|
||||
So our map now looks like:
|
||||
|
||||
```ignore
|
||||
'f' & 0xF = 0x6 |--> 00000001
|
||||
'f' >> 4 = 0x6 |--> 00000111
|
||||
'b' & 0xF = 0x2 |--> 00000110
|
||||
'b' >> 4 = 0x6 |--> 00000111
|
||||
```
|
||||
|
||||
Notice that the bitsets for each nybble correspond to the union of all
|
||||
fingerprints that contain that nybble. For example, both `f` and `b` have the
|
||||
same upper 4 bits but differ on the lower 4 bits. Putting this together, we
|
||||
have `A0`, `A1` and `B`, where `A0` is our mask for the lower nybble, `A1` is
|
||||
our mask for the upper nybble and `B` is our 16 byte block from the haystack:
|
||||
|
||||
```ignore
|
||||
0x00 0x01 0x02 0x03 ... 0x06 ... 0xF
|
||||
A0 = 0 0 00000110 0 00000001 0
|
||||
A1 = 0 0 0 0 00000111 0
|
||||
B = b a t _ t p
|
||||
B = 0x62 0x61 0x74 0x20 0x74 0x70
|
||||
```
|
||||
|
||||
But of course, we can't use `B` with `PSHUFB` yet, since its values are 8 bits,
|
||||
and we need indexes that are at most 4 bits (corresponding to one of 16
|
||||
values). We can apply the same transformation to split `B` into lower and upper
|
||||
nybbles as we did `A`. As before, `B0` corresponds to the lower nybbles and
|
||||
`B1` corresponds to the upper nybbles:
|
||||
|
||||
```ignore
|
||||
b a t _ c a t _ f o o _ b u m p
|
||||
B0 = 0x2 0x1 0x4 0x0 0x3 0x1 0x4 0x0 0x6 0xF 0xF 0x0 0x2 0x5 0xD 0x0
|
||||
B1 = 0x6 0x6 0x7 0x2 0x6 0x6 0x7 0x2 0x6 0x6 0x6 0x2 0x6 0x7 0x6 0x7
|
||||
```
|
||||
|
||||
And now we have a nice correspondence. `B0` can index `A0` and `B1` can index
|
||||
`A1`. Here's what we get when we apply `C0 = PSHUFB(A0, B0)`:
|
||||
|
||||
```ignore
|
||||
b a ... f o ... p
|
||||
A0[0x2] A0[0x1] A0[0x6] A0[0xF] A0[0x0]
|
||||
C0 = 00000110 0 00000001 0 0
|
||||
```
|
||||
|
||||
And `C1 = PSHUFB(A1, B1)`:
|
||||
|
||||
```ignore
|
||||
b a ... f o ... p
|
||||
A1[0x6] A1[0x6] A1[0x6] A1[0x6] A1[0x7]
|
||||
C1 = 00000111 00000111 00000111 00000111 0
|
||||
```
|
||||
|
||||
Notice how neither one of `C0` or `C1` is guaranteed to report fully correct
|
||||
results all on its own. For example, `C1` claims that `b` is a fingerprint for
|
||||
the pattern `foo` (since `A1[0x6] = 00000111`), and that `o` is a fingerprint
|
||||
for all of our patterns. But if we combined `C0` and `C1` with an `AND`
|
||||
operation:
|
||||
|
||||
```ignore
|
||||
b a ... f o ... p
|
||||
C = 00000110 0 00000001 0 0
|
||||
```
|
||||
|
||||
Then we now have that `C[i]` contains a bitset corresponding to the matching
|
||||
fingerprints in a haystack's 16 byte block, where `i` is the `ith` byte in that
|
||||
block.
|
||||
|
||||
Once we have that, we can look for the position of the least significant bit
|
||||
in `C`. (Least significant because we only target `x86_64` here, which is
|
||||
always little endian. Thus, the least significant bytes correspond to bytes
|
||||
in our haystack at a lower address.) That position, modulo `8`, gives us
|
||||
the pattern that the fingerprint matches. That position, integer divided by
|
||||
`8`, also gives us the byte offset that the fingerprint occurs in inside the
|
||||
16 byte haystack block. Using those two pieces of information, we can run a
|
||||
verification procedure that tries to match all substrings containing that
|
||||
fingerprint at that position in the haystack.
|
||||
|
||||
|
||||
# Implementation notes
|
||||
|
||||
The problem with the algorithm as described above is that it uses a single byte
|
||||
for a fingerprint. This will work well if the fingerprints are rare in the
|
||||
haystack (e.g., capital letters or special characters in normal English text),
|
||||
but if the fingerprints are common, you'll wind up spending too much time in
|
||||
the verification step, which effectively negates the performance benefits of
|
||||
scanning 16 bytes at a time. Remember, the key to the performance of this
|
||||
algorithm is to do as little work as possible per 16 (or 32) bytes.
|
||||
|
||||
This algorithm can be extrapolated in a relatively straight-forward way to use
|
||||
larger fingerprints. That is, instead of a single byte prefix, we might use a
|
||||
two or three byte prefix. The implementation here implements N = {1, 2, 3}
|
||||
and always picks the largest N possible. The rationale is that the bigger the
|
||||
fingerprint, the fewer verification steps we'll do. Of course, if N is too
|
||||
large, then we'll end up doing too much on each step.
|
||||
|
||||
The way to extend it is:
|
||||
|
||||
1. Add a mask for each byte in the fingerprint. (Remember that each mask is
|
||||
composed of two SIMD vectors.) This results in a value of `C` for each byte
|
||||
in the fingerprint while searching.
|
||||
2. When testing each 16 (or 32) byte block, each value of `C` must be shifted
|
||||
so that they are aligned. Once aligned, they should all be `AND`'d together.
|
||||
This will give you only the bitsets corresponding to the full match of the
|
||||
fingerprint. To do this, one needs to save the last byte (for N=2) or last
|
||||
two bytes (for N=3) from the previous iteration, and then line them up with
|
||||
the first one or two bytes of the next iteration.
|
||||
|
||||
## Verification
|
||||
|
||||
Verification generally follows the procedure outlined above. The tricky parts
|
||||
are in the right formulation of operations to get our bits out of our vectors.
|
||||
We have a limited set of operations available to us on SIMD vectors as 128-bit
|
||||
or 256-bit numbers, so we wind up needing to rip out 2 (or 4) 64-bit integers
|
||||
from our vectors, and then run our verification step on each of those. The
|
||||
verification step looks at the least significant bit set, and from its
|
||||
position, we can derive the byte offset and bucket. (Again, as described
|
||||
above.) Once we know the bucket, we do a fairly naive exhaustive search for
|
||||
every literal in that bucket. (Hyperscan is a bit smarter here and uses a hash
|
||||
table, but I haven't had time to thoroughly explore that. A few initial
|
||||
half-hearted attempts resulted in worse performance.)
|
||||
|
||||
## AVX
|
||||
|
||||
The AVX version of Teddy extrapolates almost perfectly from the SSE version.
|
||||
The only hickup is that PALIGNR is used to align chunks in the 16-bit version,
|
||||
and there is no equivalent instruction in AVX. AVX does have VPALIGNR, but it
|
||||
only works within 128-bit lanes. So there's a bit of tomfoolery to get around
|
||||
this by shuffling the vectors before calling VPALIGNR.
|
||||
|
||||
The only other aspect to AVX is that since our masks are still fundamentally
|
||||
16-bytes (0x0-0xF), they are duplicated to 32-bytes, so that they can apply to
|
||||
32-byte chunks.
|
||||
|
||||
## Fat Teddy
|
||||
|
||||
In the version of Teddy described above, 8 buckets are used to group patterns
|
||||
that we want to search for. However, when AVX is available, we can extend the
|
||||
number of buckets to 16 by permitting each byte in our masks to use 16-bits
|
||||
instead of 8-bits to represent the buckets it belongs to. (This variant is also
|
||||
in Hyperscan.) However, what we give up is the ability to scan 32 bytes at a
|
||||
time, even though we're using AVX. Instead, we have to scan 16 bytes at a time.
|
||||
What we gain, though, is (hopefully) less work in our verification routine.
|
||||
It patterns are more spread out across more buckets, then there should overall
|
||||
be fewer false positives. In general, Fat Teddy permits us to grow our capacity
|
||||
a bit and search for more literals before Teddy gets overwhelmed.
|
||||
|
||||
The tricky part of Fat Teddy is in how we adjust our masks and our verification
|
||||
procedure. For the masks, we simply represent the first 8 buckets in each of
|
||||
the low 16 bytes, and then the second 8 buckets in each of the high 16 bytes.
|
||||
Then, in the search loop, instead of loading 32 bytes from the haystack, we
|
||||
load the same 16 bytes from the haystack into both the low and high 16 byte
|
||||
portions of our 256-bit vector. So for example, a mask might look like this:
|
||||
|
||||
bits: 00100001 00000000 ... 11000000 00000000 00000001 ... 00000000
|
||||
byte: 31 30 16 15 14 0
|
||||
offset: 15 14 0 15 14 0
|
||||
buckets: 8-15 8-15 8-15 0-7 0-7 0-7
|
||||
|
||||
Where `byte` is the position in the vector (higher numbers corresponding to
|
||||
more significant bits), `offset` is the corresponding position in the haystack
|
||||
chunk, and `buckets` corresponds to the bucket assignments for that particular
|
||||
byte.
|
||||
|
||||
In particular, notice that the bucket assignments for offset `0` are spread
|
||||
out between bytes `0` and `16`. This works well for the chunk-by-chunk search
|
||||
procedure, but verification really wants to process all bucket assignments for
|
||||
each offset at once. Otherwise, we might wind up finding a match at offset
|
||||
`1` in one the first 8 buckets, when we really should have reported a match
|
||||
at offset `0` in one of the second 8 buckets. (Because we want the leftmost
|
||||
match.)
|
||||
|
||||
Thus, for verification, we rearrange the above vector such that it is a
|
||||
sequence of 16-bit integers, where the least significant 16-bit integer
|
||||
corresponds to all of the bucket assignments for offset `0`. So with the
|
||||
above vector, the least significant 16-bit integer would be
|
||||
|
||||
11000000 000000
|
||||
|
||||
which was taken from bytes `16` and `0`. Then the verification step pretty much
|
||||
runs as described, except with 16 buckets instead of 8.
|
||||
|
||||
|
||||
# References
|
||||
|
||||
- **[1]** [Hyperscan on GitHub](https://github.com/intel/hyperscan),
|
||||
[webpage](https://www.hyperscan.io/)
|
||||
- **[2a]** Ben-Kiki, O., Bille, P., Breslauer, D., Gasieniec, L., Grossi, R.,
|
||||
& Weimann, O. (2011).
|
||||
_Optimal packed string matching_.
|
||||
In LIPIcs-Leibniz International Proceedings in Informatics (Vol. 13).
|
||||
Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik.
|
||||
DOI: 10.4230/LIPIcs.FSTTCS.2011.423.
|
||||
[PDF](https://drops.dagstuhl.de/opus/volltexte/2011/3355/pdf/37.pdf).
|
||||
- **[2b]** Ben-Kiki, O., Bille, P., Breslauer, D., Ga̧sieniec, L., Grossi, R.,
|
||||
& Weimann, O. (2014).
|
||||
_Towards optimal packed string matching_.
|
||||
Theoretical Computer Science, 525, 111-129.
|
||||
DOI: 10.1016/j.tcs.2013.06.013.
|
||||
[PDF](https://www.cs.haifa.ac.il/~oren/Publications/bpsm.pdf).
|
||||
- **[3]** Bille, P. (2011).
|
||||
_Fast searching in packed strings_.
|
||||
Journal of Discrete Algorithms, 9(1), 49-56.
|
||||
DOI: 10.1016/j.jda.2010.09.003.
|
||||
[PDF](https://www.sciencedirect.com/science/article/pii/S1570866710000353).
|
||||
- **[4a]** Faro, S., & Külekci, M. O. (2012, October).
|
||||
_Fast multiple string matching using streaming SIMD extensions technology_.
|
||||
In String Processing and Information Retrieval (pp. 217-228).
|
||||
Springer Berlin Heidelberg.
|
||||
DOI: 10.1007/978-3-642-34109-0_23.
|
||||
[PDF](https://www.dmi.unict.it/faro/papers/conference/faro32.pdf).
|
||||
- **[4b]** Faro, S., & Külekci, M. O. (2013, September).
|
||||
_Towards a Very Fast Multiple String Matching Algorithm for Short Patterns_.
|
||||
In Stringology (pp. 78-91).
|
||||
[PDF](https://www.dmi.unict.it/faro/papers/conference/faro36.pdf).
|
||||
- **[4c]** Faro, S., & Külekci, M. O. (2013, January).
|
||||
_Fast packed string matching for short patterns_.
|
||||
In Proceedings of the Meeting on Algorithm Engineering & Expermiments
|
||||
(pp. 113-121).
|
||||
Society for Industrial and Applied Mathematics.
|
||||
[PDF](https://arxiv.org/pdf/1209.6449.pdf).
|
||||
- **[4d]** Faro, S., & Külekci, M. O. (2014).
|
||||
_Fast and flexible packed string matching_.
|
||||
Journal of Discrete Algorithms, 28, 61-72.
|
||||
DOI: 10.1016/j.jda.2014.07.003.
|
||||
|
||||
[1_u]: https://github.com/intel/hyperscan
|
||||
[5_u]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
|
||||
414
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/compile.rs
vendored
Normal file
414
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/compile.rs
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
// See the README in this directory for an explanation of the Teddy algorithm.
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
use crate::packed::pattern::{PatternID, Patterns};
|
||||
use crate::packed::teddy::Teddy;
|
||||
|
||||
/// A builder for constructing a Teddy matcher.
|
||||
///
|
||||
/// The builder primarily permits fine grained configuration of the Teddy
|
||||
/// matcher. Most options are made only available for testing/benchmarking
|
||||
/// purposes. In reality, options are automatically determined by the nature
|
||||
/// and number of patterns given to the builder.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Builder {
|
||||
/// When none, this is automatically determined. Otherwise, `false` means
|
||||
/// slim Teddy is used (8 buckets) and `true` means fat Teddy is used
|
||||
/// (16 buckets). Fat Teddy requires AVX2, so if that CPU feature isn't
|
||||
/// available and Fat Teddy was requested, no matcher will be built.
|
||||
fat: Option<bool>,
|
||||
/// When none, this is automatically determined. Otherwise, `false` means
|
||||
/// that 128-bit vectors will be used (up to SSSE3 instructions) where as
|
||||
/// `true` means that 256-bit vectors will be used. As with `fat`, if
|
||||
/// 256-bit vectors are requested and they aren't available, then a
|
||||
/// searcher will not be built.
|
||||
avx: Option<bool>,
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
fn default() -> Builder {
|
||||
Builder::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Create a new builder for configuring a Teddy matcher.
|
||||
pub fn new() -> Builder {
|
||||
Builder { fat: None, avx: None }
|
||||
}
|
||||
|
||||
/// Build a matcher for the set of patterns given. If a matcher could not
|
||||
/// be built, then `None` is returned.
|
||||
///
|
||||
/// Generally, a matcher isn't built if the necessary CPU features aren't
|
||||
/// available, an unsupported target or if the searcher is believed to be
|
||||
/// slower than standard techniques (i.e., if there are too many literals).
|
||||
pub fn build(&self, patterns: &Patterns) -> Option<Teddy> {
|
||||
self.build_imp(patterns)
|
||||
}
|
||||
|
||||
/// Require the use of Fat (true) or Slim (false) Teddy. Fat Teddy uses
|
||||
/// 16 buckets where as Slim Teddy uses 8 buckets. More buckets are useful
|
||||
/// for a larger set of literals.
|
||||
///
|
||||
/// `None` is the default, which results in an automatic selection based
|
||||
/// on the number of literals and available CPU features.
|
||||
pub fn fat(&mut self, yes: Option<bool>) -> &mut Builder {
|
||||
self.fat = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Request the use of 256-bit vectors (true) or 128-bit vectors (false).
|
||||
/// Generally, a larger vector size is better since it either permits
|
||||
/// matching more patterns or matching more bytes in the haystack at once.
|
||||
///
|
||||
/// `None` is the default, which results in an automatic selection based on
|
||||
/// the number of literals and available CPU features.
|
||||
pub fn avx(&mut self, yes: Option<bool>) -> &mut Builder {
|
||||
self.avx = yes;
|
||||
self
|
||||
}
|
||||
|
||||
fn build_imp(&self, patterns: &Patterns) -> Option<Teddy> {
|
||||
use crate::packed::teddy::runtime;
|
||||
|
||||
// Most of the logic here is just about selecting the optimal settings,
|
||||
// or perhaps even rejecting construction altogether. The choices
|
||||
// we have are: fat (avx only) or not, ssse3 or avx2, and how many
|
||||
// patterns we allow ourselves to search. Additionally, for testing
|
||||
// and benchmarking, we permit callers to try to "force" a setting,
|
||||
// and if the setting isn't allowed (e.g., forcing AVX when AVX isn't
|
||||
// available), then we bail and return nothing.
|
||||
|
||||
if patterns.len() > 64 {
|
||||
return None;
|
||||
}
|
||||
let has_ssse3 = is_x86_feature_detected!("ssse3");
|
||||
let has_avx = is_x86_feature_detected!("avx2");
|
||||
let avx = if self.avx == Some(true) {
|
||||
if !has_avx {
|
||||
return None;
|
||||
}
|
||||
true
|
||||
} else if self.avx == Some(false) {
|
||||
if !has_ssse3 {
|
||||
return None;
|
||||
}
|
||||
false
|
||||
} else if !has_ssse3 && !has_avx {
|
||||
return None;
|
||||
} else {
|
||||
has_avx
|
||||
};
|
||||
let fat = match self.fat {
|
||||
None => avx && patterns.len() > 32,
|
||||
Some(false) => false,
|
||||
Some(true) if !avx => return None,
|
||||
Some(true) => true,
|
||||
};
|
||||
|
||||
let mut compiler = Compiler::new(patterns, fat);
|
||||
compiler.compile();
|
||||
let Compiler { buckets, masks, .. } = compiler;
|
||||
// SAFETY: It is required that the builder only produce Teddy matchers
|
||||
// that are allowed to run on the current CPU, since we later assume
|
||||
// that the presence of (for example) TeddySlim1Mask256 means it is
|
||||
// safe to call functions marked with the `avx2` target feature.
|
||||
match (masks.len(), avx, fat) {
|
||||
(1, false, _) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddySlim1Mask128(
|
||||
runtime::TeddySlim1Mask128 {
|
||||
mask1: runtime::Mask128::new(masks[0]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(1, true, false) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddySlim1Mask256(
|
||||
runtime::TeddySlim1Mask256 {
|
||||
mask1: runtime::Mask256::new(masks[0]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(1, true, true) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddyFat1Mask256(
|
||||
runtime::TeddyFat1Mask256 {
|
||||
mask1: runtime::Mask256::new(masks[0]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(2, false, _) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddySlim2Mask128(
|
||||
runtime::TeddySlim2Mask128 {
|
||||
mask1: runtime::Mask128::new(masks[0]),
|
||||
mask2: runtime::Mask128::new(masks[1]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(2, true, false) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddySlim2Mask256(
|
||||
runtime::TeddySlim2Mask256 {
|
||||
mask1: runtime::Mask256::new(masks[0]),
|
||||
mask2: runtime::Mask256::new(masks[1]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(2, true, true) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddyFat2Mask256(
|
||||
runtime::TeddyFat2Mask256 {
|
||||
mask1: runtime::Mask256::new(masks[0]),
|
||||
mask2: runtime::Mask256::new(masks[1]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(3, false, _) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddySlim3Mask128(
|
||||
runtime::TeddySlim3Mask128 {
|
||||
mask1: runtime::Mask128::new(masks[0]),
|
||||
mask2: runtime::Mask128::new(masks[1]),
|
||||
mask3: runtime::Mask128::new(masks[2]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(3, true, false) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddySlim3Mask256(
|
||||
runtime::TeddySlim3Mask256 {
|
||||
mask1: runtime::Mask256::new(masks[0]),
|
||||
mask2: runtime::Mask256::new(masks[1]),
|
||||
mask3: runtime::Mask256::new(masks[2]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
(3, true, true) => Some(Teddy {
|
||||
buckets,
|
||||
max_pattern_id: patterns.max_pattern_id(),
|
||||
exec: runtime::Exec::TeddyFat3Mask256(
|
||||
runtime::TeddyFat3Mask256 {
|
||||
mask1: runtime::Mask256::new(masks[0]),
|
||||
mask2: runtime::Mask256::new(masks[1]),
|
||||
mask3: runtime::Mask256::new(masks[2]),
|
||||
},
|
||||
),
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A compiler is in charge of allocating patterns into buckets and generating
|
||||
/// the masks necessary for searching.
|
||||
#[derive(Clone)]
|
||||
struct Compiler<'p> {
|
||||
patterns: &'p Patterns,
|
||||
buckets: Vec<Vec<PatternID>>,
|
||||
masks: Vec<Mask>,
|
||||
}
|
||||
|
||||
impl<'p> Compiler<'p> {
|
||||
/// Create a new Teddy compiler for the given patterns. If `fat` is true,
|
||||
/// then 16 buckets will be used instead of 8.
|
||||
///
|
||||
/// This panics if any of the patterns given are empty.
|
||||
fn new(patterns: &'p Patterns, fat: bool) -> Compiler<'p> {
|
||||
let mask_len = cmp::min(3, patterns.minimum_len());
|
||||
assert!(1 <= mask_len && mask_len <= 3);
|
||||
|
||||
Compiler {
|
||||
patterns,
|
||||
buckets: vec![vec![]; if fat { 16 } else { 8 }],
|
||||
masks: vec![Mask::default(); mask_len],
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile the patterns in this compiler into buckets and masks.
|
||||
fn compile(&mut self) {
|
||||
let mut lonibble_to_bucket: BTreeMap<Vec<u8>, usize> = BTreeMap::new();
|
||||
for (id, pattern) in self.patterns.iter() {
|
||||
// We try to be slightly clever in how we assign patterns into
|
||||
// buckets. Generally speaking, we want patterns with the same
|
||||
// prefix to be in the same bucket, since it minimizes the amount
|
||||
// of time we spend churning through buckets in the verification
|
||||
// step.
|
||||
//
|
||||
// So we could assign patterns with the same N-prefix (where N
|
||||
// is the size of the mask, which is one of {1, 2, 3}) to the
|
||||
// same bucket. However, case insensitive searches are fairly
|
||||
// common, so we'd for example, ideally want to treat `abc` and
|
||||
// `ABC` as if they shared the same prefix. ASCII has the nice
|
||||
// property that the lower 4 bits of A and a are the same, so we
|
||||
// therefore group patterns with the same low-nybbe-N-prefix into
|
||||
// the same bucket.
|
||||
//
|
||||
// MOREOVER, this is actually necessary for correctness! In
|
||||
// particular, by grouping patterns with the same prefix into the
|
||||
// same bucket, we ensure that we preserve correct leftmost-first
|
||||
// and leftmost-longest match semantics. In addition to the fact
|
||||
// that `patterns.iter()` iterates in the correct order, this
|
||||
// guarantees that all possible ambiguous matches will occur in
|
||||
// the same bucket. The verification routine could be adjusted to
|
||||
// support correct leftmost match semantics regardless of bucket
|
||||
// allocation, but that results in a performance hit. It's much
|
||||
// nicer to be able to just stop as soon as a match is found.
|
||||
let lonybs = pattern.low_nybbles(self.masks.len());
|
||||
if let Some(&bucket) = lonibble_to_bucket.get(&lonybs) {
|
||||
self.buckets[bucket].push(id);
|
||||
} else {
|
||||
// N.B. We assign buckets in reverse because it shouldn't have
|
||||
// any influence on performance, but it does make it harder to
|
||||
// get leftmost match semantics accidentally correct.
|
||||
let bucket = (self.buckets.len() - 1)
|
||||
- (id as usize % self.buckets.len());
|
||||
self.buckets[bucket].push(id);
|
||||
lonibble_to_bucket.insert(lonybs, bucket);
|
||||
}
|
||||
}
|
||||
for (bucket_index, bucket) in self.buckets.iter().enumerate() {
|
||||
for &pat_id in bucket {
|
||||
let pat = self.patterns.get(pat_id);
|
||||
for (i, mask) in self.masks.iter_mut().enumerate() {
|
||||
if self.buckets.len() == 8 {
|
||||
mask.add_slim(bucket_index as u8, pat.bytes()[i]);
|
||||
} else {
|
||||
mask.add_fat(bucket_index as u8, pat.bytes()[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> fmt::Debug for Compiler<'p> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut buckets = vec![vec![]; self.buckets.len()];
|
||||
for (i, bucket) in self.buckets.iter().enumerate() {
|
||||
for &patid in bucket {
|
||||
buckets[i].push(self.patterns.get(patid));
|
||||
}
|
||||
}
|
||||
f.debug_struct("Compiler")
|
||||
.field("buckets", &buckets)
|
||||
.field("masks", &self.masks)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Mask represents the low and high nybble masks that will be used during
|
||||
/// search. Each mask is 32 bytes wide, although only the first 16 bytes are
|
||||
/// used for the SSSE3 runtime.
|
||||
///
|
||||
/// Each byte in the mask corresponds to a 8-bit bitset, where bit `i` is set
|
||||
/// if and only if the corresponding nybble is in the ith bucket. The index of
|
||||
/// the byte (0-15, inclusive) corresponds to the nybble.
|
||||
///
|
||||
/// Each mask is used as the target of a shuffle, where the indices for the
|
||||
/// shuffle are taken from the haystack. AND'ing the shuffles for both the
|
||||
/// low and high masks together also results in 8-bit bitsets, but where bit
|
||||
/// `i` is set if and only if the correspond *byte* is in the ith bucket.
|
||||
///
|
||||
/// During compilation, masks are just arrays. But during search, these masks
|
||||
/// are represented as 128-bit or 256-bit vectors.
|
||||
///
|
||||
/// (See the README is this directory for more details.)
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Mask {
|
||||
lo: [u8; 32],
|
||||
hi: [u8; 32],
|
||||
}
|
||||
|
||||
impl Mask {
|
||||
/// Update this mask by adding the given byte to the given bucket. The
|
||||
/// given bucket must be in the range 0-7.
|
||||
///
|
||||
/// This is for "slim" Teddy, where there are only 8 buckets.
|
||||
fn add_slim(&mut self, bucket: u8, byte: u8) {
|
||||
assert!(bucket < 8);
|
||||
|
||||
let byte_lo = (byte & 0xF) as usize;
|
||||
let byte_hi = ((byte >> 4) & 0xF) as usize;
|
||||
// When using 256-bit vectors, we need to set this bucket assignment in
|
||||
// the low and high 128-bit portions of the mask. This allows us to
|
||||
// process 32 bytes at a time. Namely, AVX2 shuffles operate on each
|
||||
// of the 128-bit lanes, rather than the full 256-bit vector at once.
|
||||
self.lo[byte_lo] |= 1 << bucket;
|
||||
self.lo[byte_lo + 16] |= 1 << bucket;
|
||||
self.hi[byte_hi] |= 1 << bucket;
|
||||
self.hi[byte_hi + 16] |= 1 << bucket;
|
||||
}
|
||||
|
||||
/// Update this mask by adding the given byte to the given bucket. The
|
||||
/// given bucket must be in the range 0-15.
|
||||
///
|
||||
/// This is for "fat" Teddy, where there are 16 buckets.
|
||||
fn add_fat(&mut self, bucket: u8, byte: u8) {
|
||||
assert!(bucket < 16);
|
||||
|
||||
let byte_lo = (byte & 0xF) as usize;
|
||||
let byte_hi = ((byte >> 4) & 0xF) as usize;
|
||||
// Unlike slim teddy, fat teddy only works with AVX2. For fat teddy,
|
||||
// the high 128 bits of our mask correspond to buckets 8-15, while the
|
||||
// low 128 bits correspond to buckets 0-7.
|
||||
if bucket < 8 {
|
||||
self.lo[byte_lo] |= 1 << bucket;
|
||||
self.hi[byte_hi] |= 1 << bucket;
|
||||
} else {
|
||||
self.lo[byte_lo + 16] |= 1 << (bucket % 8);
|
||||
self.hi[byte_hi + 16] |= 1 << (bucket % 8);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the low 128 bits of the low-nybble mask.
|
||||
pub fn lo128(&self) -> [u8; 16] {
|
||||
let mut tmp = [0; 16];
|
||||
tmp.copy_from_slice(&self.lo[..16]);
|
||||
tmp
|
||||
}
|
||||
|
||||
/// Return the full low-nybble mask.
|
||||
pub fn lo256(&self) -> [u8; 32] {
|
||||
self.lo
|
||||
}
|
||||
|
||||
/// Return the low 128 bits of the high-nybble mask.
|
||||
pub fn hi128(&self) -> [u8; 16] {
|
||||
let mut tmp = [0; 16];
|
||||
tmp.copy_from_slice(&self.hi[..16]);
|
||||
tmp
|
||||
}
|
||||
|
||||
/// Return the full high-nybble mask.
|
||||
pub fn hi256(&self) -> [u8; 32] {
|
||||
self.hi
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Mask {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (mut parts_lo, mut parts_hi) = (vec![], vec![]);
|
||||
for i in 0..32 {
|
||||
parts_lo.push(format!("{:02}: {:08b}", i, self.lo[i]));
|
||||
parts_hi.push(format!("{:02}: {:08b}", i, self.hi[i]));
|
||||
}
|
||||
f.debug_struct("Mask")
|
||||
.field("lo", &parts_lo)
|
||||
.field("hi", &parts_hi)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
62
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/mod.rs
vendored
Normal file
62
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/mod.rs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use crate::packed::teddy::compile::Builder;
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
pub use crate::packed::teddy::fallback::Builder;
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
pub use crate::packed::teddy::fallback::Teddy;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use crate::packed::teddy::runtime::Teddy;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod compile;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod runtime;
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
mod fallback {
|
||||
use crate::packed::pattern::Patterns;
|
||||
use crate::Match;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Builder(());
|
||||
|
||||
impl Builder {
|
||||
pub fn new() -> Builder {
|
||||
Builder(())
|
||||
}
|
||||
|
||||
pub fn build(&self, _: &Patterns) -> Option<Teddy> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn fat(&mut self, _: Option<bool>) -> &mut Builder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn avx(&mut self, _: Option<bool>) -> &mut Builder {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Teddy(());
|
||||
|
||||
impl Teddy {
|
||||
pub fn find_at(
|
||||
&self,
|
||||
_: &Patterns,
|
||||
_: &[u8],
|
||||
_: usize,
|
||||
) -> Option<Match> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn minimum_len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn heap_bytes(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
1204
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/runtime.rs
vendored
Normal file
1204
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/teddy/runtime.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
568
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/tests.rs
vendored
Normal file
568
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/tests.rs
vendored
Normal file
@@ -0,0 +1,568 @@
|
||||
use std::collections::HashMap;
|
||||
use std::usize;
|
||||
|
||||
use crate::packed::{Config, MatchKind};
|
||||
use crate::Match;
|
||||
|
||||
/// A description of a single test against a multi-pattern searcher.
|
||||
///
|
||||
/// A single test may not necessarily pass on every configuration of a
|
||||
/// searcher. The tests are categorized and grouped appropriately below.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct SearchTest {
|
||||
/// The name of this test, for debugging.
|
||||
name: &'static str,
|
||||
/// The patterns to search for.
|
||||
patterns: &'static [&'static str],
|
||||
/// The text to search.
|
||||
haystack: &'static str,
|
||||
/// Each match is a triple of (pattern_index, start, end), where
|
||||
/// pattern_index is an index into `patterns` and `start`/`end` are indices
|
||||
/// into `haystack`.
|
||||
matches: &'static [(usize, usize, usize)],
|
||||
}
|
||||
|
||||
struct SearchTestOwned {
|
||||
offset: usize,
|
||||
name: String,
|
||||
patterns: Vec<String>,
|
||||
haystack: String,
|
||||
matches: Vec<(usize, usize, usize)>,
|
||||
}
|
||||
|
||||
impl SearchTest {
|
||||
fn variations(&self) -> Vec<SearchTestOwned> {
|
||||
let mut tests = vec![];
|
||||
for i in 0..=260 {
|
||||
tests.push(self.offset_prefix(i));
|
||||
tests.push(self.offset_suffix(i));
|
||||
tests.push(self.offset_both(i));
|
||||
}
|
||||
tests
|
||||
}
|
||||
|
||||
fn offset_both(&self, off: usize) -> SearchTestOwned {
|
||||
SearchTestOwned {
|
||||
offset: off,
|
||||
name: self.name.to_string(),
|
||||
patterns: self.patterns.iter().map(|s| s.to_string()).collect(),
|
||||
haystack: format!(
|
||||
"{}{}{}",
|
||||
"Z".repeat(off),
|
||||
self.haystack,
|
||||
"Z".repeat(off)
|
||||
),
|
||||
matches: self
|
||||
.matches
|
||||
.iter()
|
||||
.map(|&(id, s, e)| (id, s + off, e + off))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_prefix(&self, off: usize) -> SearchTestOwned {
|
||||
SearchTestOwned {
|
||||
offset: off,
|
||||
name: self.name.to_string(),
|
||||
patterns: self.patterns.iter().map(|s| s.to_string()).collect(),
|
||||
haystack: format!("{}{}", "Z".repeat(off), self.haystack),
|
||||
matches: self
|
||||
.matches
|
||||
.iter()
|
||||
.map(|&(id, s, e)| (id, s + off, e + off))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_suffix(&self, off: usize) -> SearchTestOwned {
|
||||
SearchTestOwned {
|
||||
offset: off,
|
||||
name: self.name.to_string(),
|
||||
patterns: self.patterns.iter().map(|s| s.to_string()).collect(),
|
||||
haystack: format!("{}{}", self.haystack, "Z".repeat(off)),
|
||||
matches: self.matches.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
// fn to_owned(&self) -> SearchTestOwned {
|
||||
// SearchTestOwned {
|
||||
// name: self.name.to_string(),
|
||||
// patterns: self.patterns.iter().map(|s| s.to_string()).collect(),
|
||||
// haystack: self.haystack.to_string(),
|
||||
// matches: self.matches.iter().cloned().collect(),
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/// Short-hand constructor for SearchTest. We use it a lot below.
|
||||
macro_rules! t {
|
||||
($name:ident, $patterns:expr, $haystack:expr, $matches:expr) => {
|
||||
SearchTest {
|
||||
name: stringify!($name),
|
||||
patterns: $patterns,
|
||||
haystack: $haystack,
|
||||
matches: $matches,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A collection of test groups.
|
||||
type TestCollection = &'static [&'static [SearchTest]];
|
||||
|
||||
// Define several collections corresponding to the different type of match
|
||||
// semantics supported. These collections have some overlap, but each
|
||||
// collection should have some tests that no other collection has.
|
||||
|
||||
/// Tests for leftmost-first match semantics.
|
||||
const PACKED_LEFTMOST_FIRST: TestCollection =
|
||||
&[BASICS, LEFTMOST, LEFTMOST_FIRST, REGRESSION, TEDDY];
|
||||
|
||||
/// Tests for leftmost-longest match semantics.
|
||||
const PACKED_LEFTMOST_LONGEST: TestCollection =
|
||||
&[BASICS, LEFTMOST, LEFTMOST_LONGEST, REGRESSION, TEDDY];
|
||||
|
||||
// Now define the individual tests that make up the collections above.
|
||||
|
||||
/// A collection of tests for the that should always be true regardless of
|
||||
/// match semantics. That is, all combinations of leftmost-{first, longest}
|
||||
/// should produce the same answer.
|
||||
const BASICS: &'static [SearchTest] = &[
|
||||
t!(basic001, &["a"], "", &[]),
|
||||
t!(basic010, &["a"], "a", &[(0, 0, 1)]),
|
||||
t!(basic020, &["a"], "aa", &[(0, 0, 1), (0, 1, 2)]),
|
||||
t!(basic030, &["a"], "aaa", &[(0, 0, 1), (0, 1, 2), (0, 2, 3)]),
|
||||
t!(basic040, &["a"], "aba", &[(0, 0, 1), (0, 2, 3)]),
|
||||
t!(basic050, &["a"], "bba", &[(0, 2, 3)]),
|
||||
t!(basic060, &["a"], "bbb", &[]),
|
||||
t!(basic070, &["a"], "bababbbba", &[(0, 1, 2), (0, 3, 4), (0, 8, 9)]),
|
||||
t!(basic100, &["aa"], "", &[]),
|
||||
t!(basic110, &["aa"], "aa", &[(0, 0, 2)]),
|
||||
t!(basic120, &["aa"], "aabbaa", &[(0, 0, 2), (0, 4, 6)]),
|
||||
t!(basic130, &["aa"], "abbab", &[]),
|
||||
t!(basic140, &["aa"], "abbabaa", &[(0, 5, 7)]),
|
||||
t!(basic150, &["aaa"], "aaa", &[(0, 0, 3)]),
|
||||
t!(basic200, &["abc"], "abc", &[(0, 0, 3)]),
|
||||
t!(basic210, &["abc"], "zazabzabcz", &[(0, 6, 9)]),
|
||||
t!(basic220, &["abc"], "zazabczabcz", &[(0, 3, 6), (0, 7, 10)]),
|
||||
t!(basic300, &["a", "b"], "", &[]),
|
||||
t!(basic310, &["a", "b"], "z", &[]),
|
||||
t!(basic320, &["a", "b"], "b", &[(1, 0, 1)]),
|
||||
t!(basic330, &["a", "b"], "a", &[(0, 0, 1)]),
|
||||
t!(
|
||||
basic340,
|
||||
&["a", "b"],
|
||||
"abba",
|
||||
&[(0, 0, 1), (1, 1, 2), (1, 2, 3), (0, 3, 4),]
|
||||
),
|
||||
t!(
|
||||
basic350,
|
||||
&["b", "a"],
|
||||
"abba",
|
||||
&[(1, 0, 1), (0, 1, 2), (0, 2, 3), (1, 3, 4),]
|
||||
),
|
||||
t!(basic360, &["abc", "bc"], "xbc", &[(1, 1, 3),]),
|
||||
t!(basic400, &["foo", "bar"], "", &[]),
|
||||
t!(basic410, &["foo", "bar"], "foobar", &[(0, 0, 3), (1, 3, 6),]),
|
||||
t!(basic420, &["foo", "bar"], "barfoo", &[(1, 0, 3), (0, 3, 6),]),
|
||||
t!(basic430, &["foo", "bar"], "foofoo", &[(0, 0, 3), (0, 3, 6),]),
|
||||
t!(basic440, &["foo", "bar"], "barbar", &[(1, 0, 3), (1, 3, 6),]),
|
||||
t!(basic450, &["foo", "bar"], "bafofoo", &[(0, 4, 7),]),
|
||||
t!(basic460, &["bar", "foo"], "bafofoo", &[(1, 4, 7),]),
|
||||
t!(basic470, &["foo", "bar"], "fobabar", &[(1, 4, 7),]),
|
||||
t!(basic480, &["bar", "foo"], "fobabar", &[(0, 4, 7),]),
|
||||
t!(basic700, &["yabcdef", "abcdezghi"], "yabcdefghi", &[(0, 0, 7),]),
|
||||
t!(basic710, &["yabcdef", "abcdezghi"], "yabcdezghi", &[(1, 1, 10),]),
|
||||
t!(
|
||||
basic720,
|
||||
&["yabcdef", "bcdeyabc", "abcdezghi"],
|
||||
"yabcdezghi",
|
||||
&[(2, 1, 10),]
|
||||
),
|
||||
t!(basic810, &["abcd", "bcd", "cd"], "abcd", &[(0, 0, 4),]),
|
||||
t!(basic820, &["bcd", "cd", "abcd"], "abcd", &[(2, 0, 4),]),
|
||||
t!(basic830, &["abc", "bc"], "zazabcz", &[(0, 3, 6),]),
|
||||
t!(
|
||||
basic840,
|
||||
&["ab", "ba"],
|
||||
"abababa",
|
||||
&[(0, 0, 2), (0, 2, 4), (0, 4, 6),]
|
||||
),
|
||||
t!(basic850, &["foo", "foo"], "foobarfoo", &[(0, 0, 3), (0, 6, 9),]),
|
||||
];
|
||||
|
||||
/// Tests for leftmost match semantics. These should pass for both
|
||||
/// leftmost-first and leftmost-longest match kinds. Stated differently, among
|
||||
/// ambiguous matches, the longest match and the match that appeared first when
|
||||
/// constructing the automaton should always be the same.
|
||||
const LEFTMOST: &'static [SearchTest] = &[
|
||||
t!(leftmost000, &["ab", "ab"], "abcd", &[(0, 0, 2)]),
|
||||
t!(leftmost030, &["a", "ab"], "aa", &[(0, 0, 1), (0, 1, 2)]),
|
||||
t!(leftmost031, &["ab", "a"], "aa", &[(1, 0, 1), (1, 1, 2)]),
|
||||
t!(leftmost032, &["ab", "a"], "xayabbbz", &[(1, 1, 2), (0, 3, 5)]),
|
||||
t!(leftmost300, &["abcd", "bce", "b"], "abce", &[(1, 1, 4)]),
|
||||
t!(leftmost310, &["abcd", "ce", "bc"], "abce", &[(2, 1, 3)]),
|
||||
t!(leftmost320, &["abcd", "bce", "ce", "b"], "abce", &[(1, 1, 4)]),
|
||||
t!(leftmost330, &["abcd", "bce", "cz", "bc"], "abcz", &[(3, 1, 3)]),
|
||||
t!(leftmost340, &["bce", "cz", "bc"], "bcz", &[(2, 0, 2)]),
|
||||
t!(leftmost350, &["abc", "bd", "ab"], "abd", &[(2, 0, 2)]),
|
||||
t!(
|
||||
leftmost360,
|
||||
&["abcdefghi", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(2, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
leftmost370,
|
||||
&["abcdefghi", "cde", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(3, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
leftmost380,
|
||||
&["abcdefghi", "hz", "abcdefgh", "a"],
|
||||
"abcdefghz",
|
||||
&[(2, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
leftmost390,
|
||||
&["b", "abcdefghi", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(3, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
leftmost400,
|
||||
&["h", "abcdefghi", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(3, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
leftmost410,
|
||||
&["z", "abcdefghi", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(3, 0, 8), (0, 8, 9),]
|
||||
),
|
||||
];
|
||||
|
||||
/// Tests for non-overlapping leftmost-first match semantics. These tests
|
||||
/// should generally be specific to leftmost-first, which means they should
|
||||
/// generally fail under leftmost-longest semantics.
|
||||
const LEFTMOST_FIRST: &'static [SearchTest] = &[
|
||||
t!(leftfirst000, &["ab", "abcd"], "abcd", &[(0, 0, 2)]),
|
||||
t!(leftfirst020, &["abcd", "ab"], "abcd", &[(0, 0, 4)]),
|
||||
t!(leftfirst030, &["ab", "ab"], "abcd", &[(0, 0, 2)]),
|
||||
t!(leftfirst040, &["a", "ab"], "xayabbbz", &[(0, 1, 2), (0, 3, 4)]),
|
||||
t!(leftfirst100, &["abcdefg", "bcde", "bcdef"], "abcdef", &[(1, 1, 5)]),
|
||||
t!(leftfirst110, &["abcdefg", "bcdef", "bcde"], "abcdef", &[(1, 1, 6)]),
|
||||
t!(leftfirst300, &["abcd", "b", "bce"], "abce", &[(1, 1, 2)]),
|
||||
t!(
|
||||
leftfirst310,
|
||||
&["abcd", "b", "bce", "ce"],
|
||||
"abce",
|
||||
&[(1, 1, 2), (3, 2, 4),]
|
||||
),
|
||||
t!(
|
||||
leftfirst320,
|
||||
&["a", "abcdefghi", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(0, 0, 1), (2, 7, 9),]
|
||||
),
|
||||
t!(leftfirst330, &["a", "abab"], "abab", &[(0, 0, 1), (0, 2, 3)]),
|
||||
t!(
|
||||
leftfirst340,
|
||||
&["abcdef", "x", "x", "x", "x", "x", "x", "abcde"],
|
||||
"abcdef",
|
||||
&[(0, 0, 6)]
|
||||
),
|
||||
];
|
||||
|
||||
/// Tests for non-overlapping leftmost-longest match semantics. These tests
|
||||
/// should generally be specific to leftmost-longest, which means they should
|
||||
/// generally fail under leftmost-first semantics.
|
||||
const LEFTMOST_LONGEST: &'static [SearchTest] = &[
|
||||
t!(leftlong000, &["ab", "abcd"], "abcd", &[(1, 0, 4)]),
|
||||
t!(leftlong010, &["abcd", "bcd", "cd", "b"], "abcd", &[(0, 0, 4),]),
|
||||
t!(leftlong040, &["a", "ab"], "a", &[(0, 0, 1)]),
|
||||
t!(leftlong050, &["a", "ab"], "ab", &[(1, 0, 2)]),
|
||||
t!(leftlong060, &["ab", "a"], "a", &[(1, 0, 1)]),
|
||||
t!(leftlong070, &["ab", "a"], "ab", &[(0, 0, 2)]),
|
||||
t!(leftlong100, &["abcdefg", "bcde", "bcdef"], "abcdef", &[(2, 1, 6)]),
|
||||
t!(leftlong110, &["abcdefg", "bcdef", "bcde"], "abcdef", &[(1, 1, 6)]),
|
||||
t!(leftlong300, &["abcd", "b", "bce"], "abce", &[(2, 1, 4)]),
|
||||
t!(
|
||||
leftlong310,
|
||||
&["a", "abcdefghi", "hz", "abcdefgh"],
|
||||
"abcdefghz",
|
||||
&[(3, 0, 8),]
|
||||
),
|
||||
t!(leftlong320, &["a", "abab"], "abab", &[(1, 0, 4)]),
|
||||
t!(leftlong330, &["abcd", "b", "ce"], "abce", &[(1, 1, 2), (2, 2, 4),]),
|
||||
t!(leftlong340, &["a", "ab"], "xayabbbz", &[(0, 1, 2), (1, 3, 5)]),
|
||||
];
|
||||
|
||||
/// Regression tests that are applied to all combinations.
|
||||
///
|
||||
/// If regression tests are needed for specific match semantics, then add them
|
||||
/// to the appropriate group above.
|
||||
const REGRESSION: &'static [SearchTest] = &[
|
||||
t!(regression010, &["inf", "ind"], "infind", &[(0, 0, 3), (1, 3, 6),]),
|
||||
t!(regression020, &["ind", "inf"], "infind", &[(1, 0, 3), (0, 3, 6),]),
|
||||
t!(
|
||||
regression030,
|
||||
&["libcore/", "libstd/"],
|
||||
"libcore/char/methods.rs",
|
||||
&[(0, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
regression040,
|
||||
&["libstd/", "libcore/"],
|
||||
"libcore/char/methods.rs",
|
||||
&[(1, 0, 8),]
|
||||
),
|
||||
t!(
|
||||
regression050,
|
||||
&["\x00\x00\x01", "\x00\x00\x00"],
|
||||
"\x00\x00\x00",
|
||||
&[(1, 0, 3),]
|
||||
),
|
||||
t!(
|
||||
regression060,
|
||||
&["\x00\x00\x00", "\x00\x00\x01"],
|
||||
"\x00\x00\x00",
|
||||
&[(0, 0, 3),]
|
||||
),
|
||||
];
|
||||
|
||||
const TEDDY: &'static [SearchTest] = &[
|
||||
t!(
|
||||
teddy010,
|
||||
&["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"],
|
||||
"abcdefghijk",
|
||||
&[
|
||||
(0, 0, 1),
|
||||
(1, 1, 2),
|
||||
(2, 2, 3),
|
||||
(3, 3, 4),
|
||||
(4, 4, 5),
|
||||
(5, 5, 6),
|
||||
(6, 6, 7),
|
||||
(7, 7, 8),
|
||||
(8, 8, 9),
|
||||
(9, 9, 10),
|
||||
(10, 10, 11)
|
||||
]
|
||||
),
|
||||
t!(
|
||||
teddy020,
|
||||
&["ab", "bc", "cd", "de", "ef", "fg", "gh", "hi", "ij", "jk", "kl"],
|
||||
"abcdefghijk",
|
||||
&[(0, 0, 2), (2, 2, 4), (4, 4, 6), (6, 6, 8), (8, 8, 10),]
|
||||
),
|
||||
t!(
|
||||
teddy030,
|
||||
&["abc"],
|
||||
"abcdefghijklmnopqrstuvwxyzabcdefghijk",
|
||||
&[(0, 0, 3), (0, 26, 29)]
|
||||
),
|
||||
];
|
||||
|
||||
// Now define a test for each combination of things above that we want to run.
|
||||
// Since there are a few different combinations for each collection of tests,
|
||||
// we define a couple of macros to avoid repetition drudgery. The testconfig
|
||||
// macro constructs the automaton from a given match kind, and runs the search
|
||||
// tests one-by-one over the given collection. The `with` parameter allows one
|
||||
// to configure the config with additional parameters. The testcombo macro
|
||||
// invokes testconfig in precisely this way: it sets up several tests where
|
||||
// each one turns a different knob on Config.
|
||||
|
||||
macro_rules! testconfig {
|
||||
($name:ident, $collection:expr, $with:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
run_search_tests($collection, |test| {
|
||||
let mut config = Config::new();
|
||||
$with(&mut config);
|
||||
config
|
||||
.builder()
|
||||
.extend(test.patterns.iter().map(|p| p.as_bytes()))
|
||||
.build()
|
||||
.unwrap()
|
||||
.find_iter(&test.haystack)
|
||||
.collect()
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_default_leftmost_first,
|
||||
PACKED_LEFTMOST_FIRST,
|
||||
|_: &mut Config| {}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_default_leftmost_longest,
|
||||
PACKED_LEFTMOST_LONGEST,
|
||||
|c: &mut Config| {
|
||||
c.match_kind(MatchKind::LeftmostLongest);
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_leftmost_first,
|
||||
PACKED_LEFTMOST_FIRST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true);
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_leftmost_longest,
|
||||
PACKED_LEFTMOST_LONGEST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true).match_kind(MatchKind::LeftmostLongest);
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_ssse3_leftmost_first,
|
||||
PACKED_LEFTMOST_FIRST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true);
|
||||
if is_x86_feature_detected!("ssse3") {
|
||||
c.force_avx(Some(false));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_ssse3_leftmost_longest,
|
||||
PACKED_LEFTMOST_LONGEST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true).match_kind(MatchKind::LeftmostLongest);
|
||||
if is_x86_feature_detected!("ssse3") {
|
||||
c.force_avx(Some(false));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_avx2_leftmost_first,
|
||||
PACKED_LEFTMOST_FIRST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true);
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
c.force_avx(Some(true));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_avx2_leftmost_longest,
|
||||
PACKED_LEFTMOST_LONGEST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true).match_kind(MatchKind::LeftmostLongest);
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
c.force_avx(Some(true));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_fat_leftmost_first,
|
||||
PACKED_LEFTMOST_FIRST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true);
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
c.force_teddy_fat(Some(true));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
testconfig!(
|
||||
search_teddy_fat_leftmost_longest,
|
||||
PACKED_LEFTMOST_LONGEST,
|
||||
|c: &mut Config| {
|
||||
c.force_teddy(true).match_kind(MatchKind::LeftmostLongest);
|
||||
if is_x86_feature_detected!("avx2") {
|
||||
c.force_teddy_fat(Some(true));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
testconfig!(
|
||||
search_rabinkarp_leftmost_first,
|
||||
PACKED_LEFTMOST_FIRST,
|
||||
|c: &mut Config| {
|
||||
c.force_rabin_karp(true);
|
||||
}
|
||||
);
|
||||
|
||||
testconfig!(
|
||||
search_rabinkarp_leftmost_longest,
|
||||
PACKED_LEFTMOST_LONGEST,
|
||||
|c: &mut Config| {
|
||||
c.force_rabin_karp(true).match_kind(MatchKind::LeftmostLongest);
|
||||
}
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn search_tests_have_unique_names() {
|
||||
let assert = |constname, tests: &[SearchTest]| {
|
||||
let mut seen = HashMap::new(); // map from test name to position
|
||||
for (i, test) in tests.iter().enumerate() {
|
||||
if !seen.contains_key(test.name) {
|
||||
seen.insert(test.name, i);
|
||||
} else {
|
||||
let last = seen[test.name];
|
||||
panic!(
|
||||
"{} tests have duplicate names at positions {} and {}",
|
||||
constname, last, i
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
assert("BASICS", BASICS);
|
||||
assert("LEFTMOST", LEFTMOST);
|
||||
assert("LEFTMOST_FIRST", LEFTMOST_FIRST);
|
||||
assert("LEFTMOST_LONGEST", LEFTMOST_LONGEST);
|
||||
assert("REGRESSION", REGRESSION);
|
||||
assert("TEDDY", TEDDY);
|
||||
}
|
||||
|
||||
fn run_search_tests<F: FnMut(&SearchTestOwned) -> Vec<Match>>(
|
||||
which: TestCollection,
|
||||
mut f: F,
|
||||
) {
|
||||
let get_match_triples =
|
||||
|matches: Vec<Match>| -> Vec<(usize, usize, usize)> {
|
||||
matches
|
||||
.into_iter()
|
||||
.map(|m| (m.pattern(), m.start(), m.end()))
|
||||
.collect()
|
||||
};
|
||||
for &tests in which {
|
||||
for spec in tests {
|
||||
for test in spec.variations() {
|
||||
assert_eq!(
|
||||
test.matches,
|
||||
get_match_triples(f(&test)).as_slice(),
|
||||
"test: {}, patterns: {:?}, haystack: {:?}, offset: {:?}",
|
||||
test.name,
|
||||
test.patterns,
|
||||
test.haystack,
|
||||
test.offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
181
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/vector.rs
vendored
Normal file
181
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/packed/vector.rs
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
// This file contains a set of fairly generic utility functions when working
|
||||
// with SIMD vectors.
|
||||
//
|
||||
// SAFETY: All of the routines below are unsafe to call because they assume
|
||||
// the necessary CPU target features in order to use particular vendor
|
||||
// intrinsics. Calling these routines when the underlying CPU does not support
|
||||
// the appropriate target features is NOT safe. Callers must ensure this
|
||||
// themselves.
|
||||
//
|
||||
// Note that it may not look like this safety invariant is being upheld when
|
||||
// these routines are called. Namely, the CPU feature check is typically pretty
|
||||
// far away from when these routines are used. Instead, we rely on the fact
|
||||
// that certain types serve as a guaranteed receipt that pertinent target
|
||||
// features are enabled. For example, the only way TeddySlim3Mask256 can be
|
||||
// constructed is if the AVX2 CPU feature is available. Thus, any code running
|
||||
// inside of TeddySlim3Mask256 can use any of the functions below without any
|
||||
// additional checks: its very existence *is* the check.
|
||||
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
/// Shift `a` to the left by two bytes (removing its two most significant
|
||||
/// bytes), and concatenate it with the the two most significant bytes of `b`.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn alignr256_14(a: __m256i, b: __m256i) -> __m256i {
|
||||
// Credit goes to jneem for figuring this out:
|
||||
// https://github.com/jneem/teddy/blob/9ab5e899ad6ef6911aecd3cf1033f1abe6e1f66c/src/x86/teddy_simd.rs#L145-L184
|
||||
//
|
||||
// TL;DR avx2's PALIGNR instruction is actually just two 128-bit PALIGNR
|
||||
// instructions, which is not what we want, so we need to do some extra
|
||||
// shuffling.
|
||||
|
||||
// This permute gives us the low 16 bytes of a concatenated with the high
|
||||
// 16 bytes of b, in order of most significant to least significant. So
|
||||
// `v = a[15:0] b[31:16]`.
|
||||
let v = _mm256_permute2x128_si256(b, a, 0x21);
|
||||
// This effectively does this (where we deal in terms of byte-indexing
|
||||
// and byte-shifting, and use inclusive ranges):
|
||||
//
|
||||
// ret[15:0] := ((a[15:0] << 16) | v[15:0]) >> 14
|
||||
// = ((a[15:0] << 16) | b[31:16]) >> 14
|
||||
// ret[31:16] := ((a[31:16] << 16) | v[31:16]) >> 14
|
||||
// = ((a[31:16] << 16) | a[15:0]) >> 14
|
||||
//
|
||||
// Which therefore results in:
|
||||
//
|
||||
// ret[31:0] := a[29:16] a[15:14] a[13:0] b[31:30]
|
||||
//
|
||||
// The end result is that we've effectively done this:
|
||||
//
|
||||
// (a << 2) | (b >> 30)
|
||||
//
|
||||
// When `A` and `B` are strings---where the beginning of the string is in
|
||||
// the least significant bits---we effectively result in the following
|
||||
// semantic operation:
|
||||
//
|
||||
// (A >> 2) | (B << 30)
|
||||
//
|
||||
// The reversal being attributed to the fact that we are in little-endian.
|
||||
_mm256_alignr_epi8(a, v, 14)
|
||||
}
|
||||
|
||||
/// Shift `a` to the left by one byte (removing its most significant byte), and
|
||||
/// concatenate it with the the most significant byte of `b`.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn alignr256_15(a: __m256i, b: __m256i) -> __m256i {
|
||||
// For explanation, see alignr256_14.
|
||||
let v = _mm256_permute2x128_si256(b, a, 0x21);
|
||||
_mm256_alignr_epi8(a, v, 15)
|
||||
}
|
||||
|
||||
/// Unpack the given 128-bit vector into its 64-bit components. The first
|
||||
/// element of the array returned corresponds to the least significant 64-bit
|
||||
/// lane in `a`.
|
||||
#[target_feature(enable = "ssse3")]
|
||||
pub unsafe fn unpack64x128(a: __m128i) -> [u64; 2] {
|
||||
[
|
||||
_mm_cvtsi128_si64(a) as u64,
|
||||
_mm_cvtsi128_si64(_mm_srli_si128(a, 8)) as u64,
|
||||
]
|
||||
}
|
||||
|
||||
/// Unpack the given 256-bit vector into its 64-bit components. The first
|
||||
/// element of the array returned corresponds to the least significant 64-bit
|
||||
/// lane in `a`.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn unpack64x256(a: __m256i) -> [u64; 4] {
|
||||
// Using transmute here is precisely equivalent, but actually slower. It's
|
||||
// not quite clear why.
|
||||
let lo = _mm256_extracti128_si256(a, 0);
|
||||
let hi = _mm256_extracti128_si256(a, 1);
|
||||
[
|
||||
_mm_cvtsi128_si64(lo) as u64,
|
||||
_mm_cvtsi128_si64(_mm_srli_si128(lo, 8)) as u64,
|
||||
_mm_cvtsi128_si64(hi) as u64,
|
||||
_mm_cvtsi128_si64(_mm_srli_si128(hi, 8)) as u64,
|
||||
]
|
||||
}
|
||||
|
||||
/// Unpack the low 128-bits of `a` and `b`, and return them as 4 64-bit
|
||||
/// integers.
|
||||
///
|
||||
/// More precisely, if a = a4 a3 a2 a1 and b = b4 b3 b2 b1, where each element
|
||||
/// is a 64-bit integer and a1/b1 correspond to the least significant 64 bits,
|
||||
/// then the return value is `b2 b1 a2 a1`.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn unpacklo64x256(a: __m256i, b: __m256i) -> [u64; 4] {
|
||||
let lo = _mm256_castsi256_si128(a);
|
||||
let hi = _mm256_castsi256_si128(b);
|
||||
[
|
||||
_mm_cvtsi128_si64(lo) as u64,
|
||||
_mm_cvtsi128_si64(_mm_srli_si128(lo, 8)) as u64,
|
||||
_mm_cvtsi128_si64(hi) as u64,
|
||||
_mm_cvtsi128_si64(_mm_srli_si128(hi, 8)) as u64,
|
||||
]
|
||||
}
|
||||
|
||||
/// Returns true if and only if all bits in the given 128-bit vector are 0.
|
||||
#[target_feature(enable = "ssse3")]
|
||||
pub unsafe fn is_all_zeroes128(a: __m128i) -> bool {
|
||||
let cmp = _mm_cmpeq_epi8(a, zeroes128());
|
||||
_mm_movemask_epi8(cmp) as u32 == 0xFFFF
|
||||
}
|
||||
|
||||
/// Returns true if and only if all bits in the given 256-bit vector are 0.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn is_all_zeroes256(a: __m256i) -> bool {
|
||||
let cmp = _mm256_cmpeq_epi8(a, zeroes256());
|
||||
_mm256_movemask_epi8(cmp) as u32 == 0xFFFFFFFF
|
||||
}
|
||||
|
||||
/// Load a 128-bit vector from slice at the given position. The slice does
|
||||
/// not need to be unaligned.
|
||||
///
|
||||
/// Since this code assumes little-endian (there is no big-endian x86), the
|
||||
/// bytes starting in `slice[at..]` will be at the least significant bits of
|
||||
/// the returned vector. This is important for the surrounding code, since for
|
||||
/// example, shifting the resulting vector right is equivalent to logically
|
||||
/// shifting the bytes in `slice` left.
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn loadu128(slice: &[u8], at: usize) -> __m128i {
|
||||
let ptr = slice.get_unchecked(at..).as_ptr();
|
||||
_mm_loadu_si128(ptr as *const u8 as *const __m128i)
|
||||
}
|
||||
|
||||
/// Load a 256-bit vector from slice at the given position. The slice does
|
||||
/// not need to be unaligned.
|
||||
///
|
||||
/// Since this code assumes little-endian (there is no big-endian x86), the
|
||||
/// bytes starting in `slice[at..]` will be at the least significant bits of
|
||||
/// the returned vector. This is important for the surrounding code, since for
|
||||
/// example, shifting the resulting vector right is equivalent to logically
|
||||
/// shifting the bytes in `slice` left.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn loadu256(slice: &[u8], at: usize) -> __m256i {
|
||||
let ptr = slice.get_unchecked(at..).as_ptr();
|
||||
_mm256_loadu_si256(ptr as *const u8 as *const __m256i)
|
||||
}
|
||||
|
||||
/// Returns a 128-bit vector with all bits set to 0.
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn zeroes128() -> __m128i {
|
||||
_mm_set1_epi8(0)
|
||||
}
|
||||
|
||||
/// Returns a 256-bit vector with all bits set to 0.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn zeroes256() -> __m256i {
|
||||
_mm256_set1_epi8(0)
|
||||
}
|
||||
|
||||
/// Returns a 128-bit vector with all bits set to 1.
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn ones128() -> __m128i {
|
||||
_mm_set1_epi8(0xFF as u8 as i8)
|
||||
}
|
||||
|
||||
/// Returns a 256-bit vector with all bits set to 1.
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub unsafe fn ones256() -> __m256i {
|
||||
_mm256_set1_epi8(0xFF as u8 as i8)
|
||||
}
|
||||
1057
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/prefilter.rs
vendored
Normal file
1057
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/prefilter.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
192
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/state_id.rs
vendored
Normal file
192
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/state_id.rs
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
|
||||
// NOTE: Most of this code was copied from regex-automata, but without the
|
||||
// (de)serialization specific stuff.
|
||||
|
||||
/// Check that the premultiplication of the given state identifier can
|
||||
/// fit into the representation indicated by `S`. If it cannot, or if it
|
||||
/// overflows `usize` itself, then an error is returned.
|
||||
pub fn premultiply_overflow_error<S: StateID>(
|
||||
last_state: S,
|
||||
alphabet_len: usize,
|
||||
) -> Result<()> {
|
||||
let requested = match last_state.to_usize().checked_mul(alphabet_len) {
|
||||
Some(requested) => requested,
|
||||
None => return Err(Error::premultiply_overflow(0, 0)),
|
||||
};
|
||||
if requested > S::max_id() {
|
||||
return Err(Error::premultiply_overflow(S::max_id(), requested));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert the given `usize` to the chosen state identifier
|
||||
/// representation. If the given value cannot fit in the chosen
|
||||
/// representation, then an error is returned.
|
||||
pub fn usize_to_state_id<S: StateID>(value: usize) -> Result<S> {
|
||||
if value > S::max_id() {
|
||||
Err(Error::state_id_overflow(S::max_id()))
|
||||
} else {
|
||||
Ok(S::from_usize(value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the unique identifier for an automaton's fail state in the chosen
|
||||
/// representation indicated by `S`.
|
||||
pub fn fail_id<S: StateID>() -> S {
|
||||
S::from_usize(0)
|
||||
}
|
||||
|
||||
/// Return the unique identifier for an automaton's fail state in the chosen
|
||||
/// representation indicated by `S`.
|
||||
pub fn dead_id<S: StateID>() -> S {
|
||||
S::from_usize(1)
|
||||
}
|
||||
|
||||
mod private {
|
||||
/// Sealed stops crates other than aho-corasick from implementing any
|
||||
/// traits that use it.
|
||||
pub trait Sealed {}
|
||||
impl Sealed for u8 {}
|
||||
impl Sealed for u16 {}
|
||||
impl Sealed for u32 {}
|
||||
impl Sealed for u64 {}
|
||||
impl Sealed for usize {}
|
||||
}
|
||||
|
||||
/// A trait describing the representation of an automaton's state identifier.
|
||||
///
|
||||
/// The purpose of this trait is to safely express both the possible state
|
||||
/// identifier representations that can be used in an automaton and to convert
|
||||
/// between state identifier representations and types that can be used to
|
||||
/// efficiently index memory (such as `usize`).
|
||||
///
|
||||
/// In general, one should not need to implement this trait explicitly. Indeed,
|
||||
/// for now, this trait is sealed such that it cannot be implemented by any
|
||||
/// other type. In particular, this crate provides implementations for `u8`,
|
||||
/// `u16`, `u32`, `u64` and `usize`. (`u32` and `u64` are only provided for
|
||||
/// targets that can represent all corresponding values in a `usize`.)
|
||||
pub trait StateID:
|
||||
private::Sealed
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Debug
|
||||
+ Eq
|
||||
+ Hash
|
||||
+ PartialEq
|
||||
+ PartialOrd
|
||||
+ Ord
|
||||
{
|
||||
/// Convert from a `usize` to this implementation's representation.
|
||||
///
|
||||
/// Implementors may assume that `n <= Self::max_id`. That is, implementors
|
||||
/// do not need to check whether `n` can fit inside this implementation's
|
||||
/// representation.
|
||||
fn from_usize(n: usize) -> Self;
|
||||
|
||||
/// Convert this implementation's representation to a `usize`.
|
||||
///
|
||||
/// Implementors must not return a `usize` value greater than
|
||||
/// `Self::max_id` and must not permit overflow when converting between the
|
||||
/// implementor's representation and `usize`. In general, the preferred
|
||||
/// way for implementors to achieve this is to simply not provide
|
||||
/// implementations of `StateID` that cannot fit into the target platform's
|
||||
/// `usize`.
|
||||
fn to_usize(self) -> usize;
|
||||
|
||||
/// Return the maximum state identifier supported by this representation.
|
||||
///
|
||||
/// Implementors must return a correct bound. Doing otherwise may result
|
||||
/// in unspecified behavior (but will not violate memory safety).
|
||||
fn max_id() -> usize;
|
||||
}
|
||||
|
||||
impl StateID for usize {
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> usize {
|
||||
n
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_usize(self) -> usize {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_id() -> usize {
|
||||
::std::usize::MAX
|
||||
}
|
||||
}
|
||||
|
||||
impl StateID for u8 {
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> u8 {
|
||||
n as u8
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_usize(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_id() -> usize {
|
||||
::std::u8::MAX as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl StateID for u16 {
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> u16 {
|
||||
n as u16
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_usize(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_id() -> usize {
|
||||
::std::u16::MAX as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
|
||||
impl StateID for u32 {
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> u32 {
|
||||
n as u32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_usize(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_id() -> usize {
|
||||
::std::u32::MAX as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
impl StateID for u64 {
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> u64 {
|
||||
n as u64
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_usize(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_id() -> usize {
|
||||
::std::u64::MAX as usize
|
||||
}
|
||||
}
|
||||
1254
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/tests.rs
vendored
Normal file
1254
clamav/libclamav_rust/.cargo/vendor/aho-corasick/src/tests.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
clamav/libclamav_rust/.cargo/vendor/ansi_term/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/ansi_term/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"Cargo.lock":"31bb7b361278d99a00595cbd916c444e6fd193b5f0b1ea0cf2d9454440739501","Cargo.toml":"4ca681d6949661455ac88541ffa68ebc7db50cb2b6e9a2134e6d0687da4997c3","LICENCE":"2762990c7fbba9d550802a2593c1d857dcd52596bb0f9f192a97e9a7ac5f4f9e","README.md":"8d983e1bb3cc99724010d9073a5be6452cd49bd57a877525fd0a5dd41e6591d5","examples/256_colours.rs":"5f2845068bc2d93cff4a61f18ffa44fbbbc91be771dfd686d537d343f37041da","examples/basic_colours.rs":"d610795f3743d10d90ec4e5ab32cc09fb16640896cecd2f93fca434a0920397c","examples/rgb_colours.rs":"8399e5131e959a56c932036b790e601fb4ad658856112daf87f933889b443f2c","src/ansi.rs":"988fb87936064fa006fcc9474ac62099c8d6e98d38bb80cec2cd864066482a08","src/debug.rs":"61343f8bf13695020102c033aeaacd9ccd3ec830eacbf9011127e61829451d20","src/difference.rs":"9b4b8f91c72932bfda262abdceff0ec124a5a8dd27d07bd4d2e5e7889135c6c9","src/display.rs":"c04f2397d1d1d86a5e2188c2840c505cb0baeaf9706a88d4bbe56eadc67811b9","src/lib.rs":"b85df4b9b8832cda777db049efa2ec84b9847438fa3feaf8540e597ce2532a47","src/style.rs":"1042fc973f5ea8bbb2a2faec334aad530520b53edc9b3296174ae38c1060490b","src/util.rs":"07c127f732887573a1c9126fc0288e13e7a8f1f803513b95e50aac2905171b0d","src/windows.rs":"7ce7dd6738b9728fcd3908c284b6f29a9bdfb34af761b4c7385cf7e3e1b20e64","src/write.rs":"c9ec03764ad1ecea8b680243c9cafc5e70919fcea7500cc18246ffd8f6bb4b33"},"package":"d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"}
|
||||
168
clamav/libclamav_rust/.cargo/vendor/ansi_term/Cargo.lock
generated
vendored
Normal file
168
clamav/libclamav_rust/.cargo/vendor/ansi_term/Cargo.lock
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
dependencies = [
|
||||
"doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||
"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97"
|
||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26"
|
||||
"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
|
||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
||||
"checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b"
|
||||
"checksum serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "ef45eb79d6463b22f5f9e16d283798b7c0175ba6050bc25c1a946c122727fe7b"
|
||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
43
clamav/libclamav_rust/.cargo/vendor/ansi_term/Cargo.toml
vendored
Normal file
43
clamav/libclamav_rust/.cargo/vendor/ansi_term/Cargo.toml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# 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 = "ansi_term"
|
||||
version = "0.12.1"
|
||||
authors = ["ogham@bsago.me", "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>", "Josh Triplett <josh@joshtriplett.org>"]
|
||||
description = "Library for ANSI terminal colours and styles (bold, underline)"
|
||||
homepage = "https://github.com/ogham/rust-ansi-term"
|
||||
documentation = "https://docs.rs/ansi_term"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/ogham/rust-ansi-term"
|
||||
|
||||
[lib]
|
||||
name = "ansi_term"
|
||||
[dependencies.serde]
|
||||
version = "1.0.90"
|
||||
features = ["derive"]
|
||||
optional = true
|
||||
[dev-dependencies.doc-comment]
|
||||
version = "0.3"
|
||||
|
||||
[dev-dependencies.regex]
|
||||
version = "1.1.9"
|
||||
|
||||
[dev-dependencies.serde_json]
|
||||
version = "1.0.39"
|
||||
|
||||
[features]
|
||||
derive_serde_style = ["serde"]
|
||||
[target."cfg(target_os=\"windows\")".dependencies.winapi]
|
||||
version = "0.3.4"
|
||||
features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"]
|
||||
21
clamav/libclamav_rust/.cargo/vendor/ansi_term/LICENCE
vendored
Normal file
21
clamav/libclamav_rust/.cargo/vendor/ansi_term/LICENCE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Benjamin Sago
|
||||
|
||||
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.
|
||||
183
clamav/libclamav_rust/.cargo/vendor/ansi_term/README.md
vendored
Normal file
183
clamav/libclamav_rust/.cargo/vendor/ansi_term/README.md
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
# rust-ansi-term [](https://crates.io/crates/ansi_term) [](https://travis-ci.org/ogham/rust-ansi-term) [](https://ci.appveyor.com/project/ogham/rust-ansi-term) [](https://coveralls.io/github/ogham/rust-ansi-term?branch=master)
|
||||
|
||||
This is a library for controlling colours and formatting, such as red bold text or blue underlined text, on ANSI terminals.
|
||||
|
||||
### [View the Rustdoc](https://docs.rs/ansi_term/)
|
||||
|
||||
|
||||
# Installation
|
||||
|
||||
This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
ansi_term = "0.12"
|
||||
```
|
||||
|
||||
|
||||
## Basic usage
|
||||
|
||||
There are three main types in this crate that you need to be concerned with: `ANSIString`, `Style`, and `Colour`.
|
||||
|
||||
A `Style` holds stylistic information: foreground and background colours, whether the text should be bold, or blinking, or other properties.
|
||||
The `Colour` enum represents the available colours.
|
||||
And an `ANSIString` is a string paired with a `Style`.
|
||||
|
||||
`Color` is also available as an alias to `Colour`.
|
||||
|
||||
To format a string, call the `paint` method on a `Style` or a `Colour`, passing in the string you want to format as the argument.
|
||||
For example, here’s how to get some red text:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::Red;
|
||||
|
||||
println!("This is in red: {}", Red.paint("a red string"));
|
||||
```
|
||||
|
||||
It’s important to note that the `paint` method does *not* actually return a string with the ANSI control characters surrounding it.
|
||||
Instead, it returns an `ANSIString` value that has a `Display` implementation that, when formatted, returns the characters.
|
||||
This allows strings to be printed with a minimum of `String` allocations being performed behind the scenes.
|
||||
|
||||
If you *do* want to get at the escape codes, then you can convert the `ANSIString` to a string as you would any other `Display` value:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::Red;
|
||||
|
||||
let red_string = Red.paint("a red string").to_string();
|
||||
```
|
||||
|
||||
**Note for Windows 10 users:** On Windows 10, the application must enable ANSI support first:
|
||||
|
||||
```rust,ignore
|
||||
let enabled = ansi_term::enable_ansi_support();
|
||||
```
|
||||
|
||||
## Bold, underline, background, and other styles
|
||||
|
||||
For anything more complex than plain foreground colour changes, you need to construct `Style` values themselves, rather than beginning with a `Colour`.
|
||||
You can do this by chaining methods based on a new `Style`, created with `Style::new()`.
|
||||
Each method creates a new style that has that specific property set.
|
||||
For example:
|
||||
|
||||
```rust
|
||||
use ansi_term::Style;
|
||||
|
||||
println!("How about some {} and {}?",
|
||||
Style::new().bold().paint("bold"),
|
||||
Style::new().underline().paint("underline"));
|
||||
```
|
||||
|
||||
For brevity, these methods have also been implemented for `Colour` values, so you can give your styles a foreground colour without having to begin with an empty `Style` value:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::{Blue, Yellow};
|
||||
|
||||
println!("Demonstrating {} and {}!",
|
||||
Blue.bold().paint("blue bold"),
|
||||
Yellow.underline().paint("yellow underline"));
|
||||
|
||||
println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
|
||||
```
|
||||
|
||||
The complete list of styles you can use are:
|
||||
`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colours.
|
||||
|
||||
In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Colour`.
|
||||
You can do this using the `fg` method:
|
||||
|
||||
```rust
|
||||
use ansi_term::Style;
|
||||
use ansi_term::Colour::{Blue, Cyan, Yellow};
|
||||
|
||||
println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
|
||||
println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
|
||||
```
|
||||
|
||||
You can turn a `Colour` into a `Style` with the `normal` method.
|
||||
This will produce the exact same `ANSIString` as if you just used the `paint` method on the `Colour` directly, but it’s useful in certain cases: for example, you may have a method that returns `Styles`, and need to represent both the “red bold” and “red, but not bold” styles with values of the same type. The `Style` struct also has a `Default` implementation if you want to have a style with *nothing* set.
|
||||
|
||||
```rust
|
||||
use ansi_term::Style;
|
||||
use ansi_term::Colour::Red;
|
||||
|
||||
Red.normal().paint("yet another red string");
|
||||
Style::default().paint("a completely regular string");
|
||||
```
|
||||
|
||||
|
||||
## Extended colours
|
||||
|
||||
You can access the extended range of 256 colours by using the `Colour::Fixed` variant, which takes an argument of the colour number to use.
|
||||
This can be included wherever you would use a `Colour`:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::Fixed;
|
||||
|
||||
Fixed(134).paint("A sort of light purple");
|
||||
Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
|
||||
```
|
||||
|
||||
The first sixteen of these values are the same as the normal and bold standard colour variants.
|
||||
There’s nothing stopping you from using these as `Fixed` colours instead, but there’s nothing to be gained by doing so either.
|
||||
|
||||
You can also access full 24-bit colour by using the `Colour::RGB` variant, which takes separate `u8` arguments for red, green, and blue:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::RGB;
|
||||
|
||||
RGB(70, 130, 180).paint("Steel blue");
|
||||
```
|
||||
|
||||
## Combining successive coloured strings
|
||||
|
||||
The benefit of writing ANSI escape codes to the terminal is that they *stack*: you do not need to end every coloured string with a reset code if the text that follows it is of a similar style.
|
||||
For example, if you want to have some blue text followed by some blue bold text, it’s possible to send the ANSI code for blue, followed by the ANSI code for bold, and finishing with a reset code without having to have an extra one between the two strings.
|
||||
|
||||
This crate can optimise the ANSI codes that get printed in situations like this, making life easier for your terminal renderer.
|
||||
The `ANSIStrings` struct takes a slice of several `ANSIString` values, and will iterate over each of them, printing only the codes for the styles that need to be updated as part of its formatting routine.
|
||||
|
||||
The following code snippet uses this to enclose a binary number displayed in red bold text inside some red, but not bold, brackets:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::Red;
|
||||
use ansi_term::{ANSIString, ANSIStrings};
|
||||
|
||||
let some_value = format!("{:b}", 42);
|
||||
let strings: &[ANSIString<'static>] = &[
|
||||
Red.paint("["),
|
||||
Red.bold().paint(some_value),
|
||||
Red.paint("]"),
|
||||
];
|
||||
|
||||
println!("Value: {}", ANSIStrings(strings));
|
||||
```
|
||||
|
||||
There are several things to note here.
|
||||
Firstly, the `paint` method can take *either* an owned `String` or a borrowed `&str`.
|
||||
Internally, an `ANSIString` holds a copy-on-write (`Cow`) string value to deal with both owned and borrowed strings at the same time.
|
||||
This is used here to display a `String`, the result of the `format!` call, using the same mechanism as some statically-available `&str` slices.
|
||||
Secondly, that the `ANSIStrings` value works in the same way as its singular counterpart, with a `Display` implementation that only performs the formatting when required.
|
||||
|
||||
## Byte strings
|
||||
|
||||
This library also supports formatting `[u8]` byte strings; this supports applications working with text in an unknown encoding.
|
||||
`Style` and `Colour` support painting `[u8]` values, resulting in an `ANSIByteString`.
|
||||
This type does not implement `Display`, as it may not contain UTF-8, but it does provide a method `write_to` to write the result to any value that implements `Write`:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::Green;
|
||||
|
||||
Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
|
||||
```
|
||||
|
||||
Similarly, the type `ANSIByteStrings` supports writing a list of `ANSIByteString` values with minimal escape sequences:
|
||||
|
||||
```rust
|
||||
use ansi_term::Colour::Green;
|
||||
use ansi_term::ANSIByteStrings;
|
||||
|
||||
ANSIByteStrings(&[
|
||||
Green.paint("user data 1\n".as_bytes()),
|
||||
Green.bold().paint("user data 2\n".as_bytes()),
|
||||
]).write_to(&mut std::io::stdout()).unwrap();
|
||||
```
|
||||
73
clamav/libclamav_rust/.cargo/vendor/ansi_term/examples/256_colours.rs
vendored
Normal file
73
clamav/libclamav_rust/.cargo/vendor/ansi_term/examples/256_colours.rs
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
extern crate ansi_term;
|
||||
use ansi_term::Colour;
|
||||
|
||||
// This example prints out the 256 colours.
|
||||
// They're arranged like this:
|
||||
//
|
||||
// - 0 to 8 are the eight standard colours.
|
||||
// - 9 to 15 are the eight bold colours.
|
||||
// - 16 to 231 are six blocks of six-by-six colour squares.
|
||||
// - 232 to 255 are shades of grey.
|
||||
|
||||
fn main() {
|
||||
|
||||
// First two lines
|
||||
for c in 0..8 {
|
||||
glow(c, c != 0);
|
||||
print!(" ");
|
||||
}
|
||||
print!("\n");
|
||||
for c in 8..16 {
|
||||
glow(c, c != 8);
|
||||
print!(" ");
|
||||
}
|
||||
print!("\n\n");
|
||||
|
||||
// Six lines of the first three squares
|
||||
for row in 0..6 {
|
||||
for square in 0..3 {
|
||||
for column in 0..6 {
|
||||
glow(16 + square * 36 + row * 6 + column, row >= 3);
|
||||
print!(" ");
|
||||
}
|
||||
|
||||
print!(" ");
|
||||
}
|
||||
|
||||
print!("\n");
|
||||
}
|
||||
print!("\n");
|
||||
|
||||
// Six more lines of the other three squares
|
||||
for row in 0..6 {
|
||||
for square in 0..3 {
|
||||
for column in 0..6 {
|
||||
glow(124 + square * 36 + row * 6 + column, row >= 3);
|
||||
print!(" ");
|
||||
}
|
||||
|
||||
print!(" ");
|
||||
}
|
||||
|
||||
print!("\n");
|
||||
}
|
||||
print!("\n");
|
||||
|
||||
// The last greyscale lines
|
||||
for c in 232..=243 {
|
||||
glow(c, false);
|
||||
print!(" ");
|
||||
}
|
||||
print!("\n");
|
||||
for c in 244..=255 {
|
||||
glow(c, true);
|
||||
print!(" ");
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
|
||||
fn glow(c: u8, light_bg: bool) {
|
||||
let base = if light_bg { Colour::Black } else { Colour::White };
|
||||
let style = base.on(Colour::Fixed(c));
|
||||
print!("{}", style.paint(&format!(" {:3} ", c)));
|
||||
}
|
||||
18
clamav/libclamav_rust/.cargo/vendor/ansi_term/examples/basic_colours.rs
vendored
Normal file
18
clamav/libclamav_rust/.cargo/vendor/ansi_term/examples/basic_colours.rs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
extern crate ansi_term;
|
||||
use ansi_term::{Style, Colour::*};
|
||||
|
||||
// This example prints out the 16 basic colours.
|
||||
|
||||
fn main() {
|
||||
let normal = Style::default();
|
||||
|
||||
println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold"));
|
||||
println!("{} {}", Black.paint("Black"), Black.bold().paint("bold"));
|
||||
println!("{} {}", Red.paint("Red"), Red.bold().paint("bold"));
|
||||
println!("{} {}", Green.paint("Green"), Green.bold().paint("bold"));
|
||||
println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold"));
|
||||
println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold"));
|
||||
println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold"));
|
||||
println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold"));
|
||||
println!("{} {}", White.paint("White"), White.bold().paint("bold"));
|
||||
}
|
||||
23
clamav/libclamav_rust/.cargo/vendor/ansi_term/examples/rgb_colours.rs
vendored
Normal file
23
clamav/libclamav_rust/.cargo/vendor/ansi_term/examples/rgb_colours.rs
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
extern crate ansi_term;
|
||||
use ansi_term::{Style, Colour};
|
||||
|
||||
// This example prints out a colour gradient in a grid by calculating each
|
||||
// character’s red, green, and blue components, and using 24-bit colour codes
|
||||
// to display them.
|
||||
|
||||
const WIDTH: i32 = 80;
|
||||
const HEIGHT: i32 = 24;
|
||||
|
||||
fn main() {
|
||||
for row in 0 .. HEIGHT {
|
||||
for col in 0 .. WIDTH {
|
||||
let r = (row * 255 / HEIGHT) as u8;
|
||||
let g = (col * 255 / WIDTH) as u8;
|
||||
let b = 128;
|
||||
|
||||
print!("{}", Style::default().on(Colour::RGB(r, g, b)).paint(" "));
|
||||
}
|
||||
|
||||
print!("\n");
|
||||
}
|
||||
}
|
||||
374
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/ansi.rs
vendored
Normal file
374
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/ansi.rs
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
use style::{Colour, Style};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use write::AnyWrite;
|
||||
|
||||
|
||||
// ---- generating ANSI codes ----
|
||||
|
||||
impl Style {
|
||||
|
||||
/// Write any bytes that go *before* a piece of text to the given writer.
|
||||
fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
||||
|
||||
// If there are actually no styles here, then don’t write *any* codes
|
||||
// as the prefix. An empty ANSI code may not affect the terminal
|
||||
// output at all, but a user may just want a code-free string.
|
||||
if self.is_plain() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Write the codes’ prefix, then write numbers, separated by
|
||||
// semicolons, for each text style we want to apply.
|
||||
write!(f, "\x1B[")?;
|
||||
let mut written_anything = false;
|
||||
|
||||
{
|
||||
let mut write_char = |c| {
|
||||
if written_anything { write!(f, ";")?; }
|
||||
written_anything = true;
|
||||
write!(f, "{}", c)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
if self.is_bold { write_char('1')? }
|
||||
if self.is_dimmed { write_char('2')? }
|
||||
if self.is_italic { write_char('3')? }
|
||||
if self.is_underline { write_char('4')? }
|
||||
if self.is_blink { write_char('5')? }
|
||||
if self.is_reverse { write_char('7')? }
|
||||
if self.is_hidden { write_char('8')? }
|
||||
if self.is_strikethrough { write_char('9')? }
|
||||
}
|
||||
|
||||
// The foreground and background colours, if specified, need to be
|
||||
// handled specially because the number codes are more complicated.
|
||||
// (see `write_background_code` and `write_foreground_code`)
|
||||
if let Some(bg) = self.background {
|
||||
if written_anything { write!(f, ";")?; }
|
||||
written_anything = true;
|
||||
bg.write_background_code(f)?;
|
||||
}
|
||||
|
||||
if let Some(fg) = self.foreground {
|
||||
if written_anything { write!(f, ";")?; }
|
||||
fg.write_foreground_code(f)?;
|
||||
}
|
||||
|
||||
// All the codes end with an `m`, because reasons.
|
||||
write!(f, "m")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write any bytes that go *after* a piece of text to the given writer.
|
||||
fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
||||
if self.is_plain() {
|
||||
Ok(())
|
||||
}
|
||||
else {
|
||||
write!(f, "{}", RESET)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The code to send to reset all styles and return to `Style::default()`.
|
||||
pub static RESET: &str = "\x1B[0m";
|
||||
|
||||
|
||||
|
||||
impl Colour {
|
||||
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
||||
match *self {
|
||||
Colour::Black => write!(f, "30"),
|
||||
Colour::Red => write!(f, "31"),
|
||||
Colour::Green => write!(f, "32"),
|
||||
Colour::Yellow => write!(f, "33"),
|
||||
Colour::Blue => write!(f, "34"),
|
||||
Colour::Purple => write!(f, "35"),
|
||||
Colour::Cyan => write!(f, "36"),
|
||||
Colour::White => write!(f, "37"),
|
||||
Colour::Fixed(num) => write!(f, "38;5;{}", &num),
|
||||
Colour::RGB(r,g,b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
|
||||
match *self {
|
||||
Colour::Black => write!(f, "40"),
|
||||
Colour::Red => write!(f, "41"),
|
||||
Colour::Green => write!(f, "42"),
|
||||
Colour::Yellow => write!(f, "43"),
|
||||
Colour::Blue => write!(f, "44"),
|
||||
Colour::Purple => write!(f, "45"),
|
||||
Colour::Cyan => write!(f, "46"),
|
||||
Colour::White => write!(f, "47"),
|
||||
Colour::Fixed(num) => write!(f, "48;5;{}", &num),
|
||||
Colour::RGB(r,g,b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Like `ANSIString`, but only displays the style prefix.
|
||||
///
|
||||
/// This type implements the `Display` trait, meaning it can be written to a
|
||||
/// `std::fmt` formatting without doing any extra allocation, and written to a
|
||||
/// string with the `.to_string()` method. For examples, see
|
||||
/// [`Style::prefix`](struct.Style.html#method.prefix).
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Prefix(Style);
|
||||
|
||||
/// Like `ANSIString`, but only displays the difference between two
|
||||
/// styles.
|
||||
///
|
||||
/// This type implements the `Display` trait, meaning it can be written to a
|
||||
/// `std::fmt` formatting without doing any extra allocation, and written to a
|
||||
/// string with the `.to_string()` method. For examples, see
|
||||
/// [`Style::infix`](struct.Style.html#method.infix).
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Infix(Style, Style);
|
||||
|
||||
/// Like `ANSIString`, but only displays the style suffix.
|
||||
///
|
||||
/// This type implements the `Display` trait, meaning it can be written to a
|
||||
/// `std::fmt` formatting without doing any extra allocation, and written to a
|
||||
/// string with the `.to_string()` method. For examples, see
|
||||
/// [`Style::suffix`](struct.Style.html#method.suffix).
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Suffix(Style);
|
||||
|
||||
|
||||
impl Style {
|
||||
|
||||
/// The prefix bytes for this style. These are the bytes that tell the
|
||||
/// terminal to use a different colour or font style.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour::Blue};
|
||||
///
|
||||
/// let style = Style::default().bold();
|
||||
/// assert_eq!("\x1b[1m",
|
||||
/// style.prefix().to_string());
|
||||
///
|
||||
/// let style = Blue.bold();
|
||||
/// assert_eq!("\x1b[1;34m",
|
||||
/// style.prefix().to_string());
|
||||
///
|
||||
/// let style = Style::default();
|
||||
/// assert_eq!("",
|
||||
/// style.prefix().to_string());
|
||||
/// ```
|
||||
pub fn prefix(self) -> Prefix {
|
||||
Prefix(self)
|
||||
}
|
||||
|
||||
/// The infix bytes between this style and `next` style. These are the bytes
|
||||
/// that tell the terminal to change the style to `next`. These may include
|
||||
/// a reset followed by the next colour and style, depending on the two styles.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour::Green};
|
||||
///
|
||||
/// let style = Style::default().bold();
|
||||
/// assert_eq!("\x1b[32m",
|
||||
/// style.infix(Green.bold()).to_string());
|
||||
///
|
||||
/// let style = Green.normal();
|
||||
/// assert_eq!("\x1b[1m",
|
||||
/// style.infix(Green.bold()).to_string());
|
||||
///
|
||||
/// let style = Style::default();
|
||||
/// assert_eq!("",
|
||||
/// style.infix(style).to_string());
|
||||
/// ```
|
||||
pub fn infix(self, next: Style) -> Infix {
|
||||
Infix(self, next)
|
||||
}
|
||||
|
||||
/// The suffix for this style. These are the bytes that tell the terminal
|
||||
/// to reset back to its normal colour and font style.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour::Green};
|
||||
///
|
||||
/// let style = Style::default().bold();
|
||||
/// assert_eq!("\x1b[0m",
|
||||
/// style.suffix().to_string());
|
||||
///
|
||||
/// let style = Green.normal().bold();
|
||||
/// assert_eq!("\x1b[0m",
|
||||
/// style.suffix().to_string());
|
||||
///
|
||||
/// let style = Style::default();
|
||||
/// assert_eq!("",
|
||||
/// style.suffix().to_string());
|
||||
/// ```
|
||||
pub fn suffix(self) -> Suffix {
|
||||
Suffix(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Colour {
|
||||
|
||||
/// The prefix bytes for this colour as a `Style`. These are the bytes
|
||||
/// that tell the terminal to use a different colour or font style.
|
||||
///
|
||||
/// See also [`Style::prefix`](struct.Style.html#method.prefix).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour::Green;
|
||||
///
|
||||
/// assert_eq!("\x1b[0m",
|
||||
/// Green.suffix().to_string());
|
||||
/// ```
|
||||
pub fn prefix(self) -> Prefix {
|
||||
Prefix(self.normal())
|
||||
}
|
||||
|
||||
/// The infix bytes between this colour and `next` colour. These are the bytes
|
||||
/// that tell the terminal to use the `next` colour, or to do nothing if
|
||||
/// the two colours are equal.
|
||||
///
|
||||
/// See also [`Style::infix`](struct.Style.html#method.infix).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour::{Red, Yellow};
|
||||
///
|
||||
/// assert_eq!("\x1b[33m",
|
||||
/// Red.infix(Yellow).to_string());
|
||||
/// ```
|
||||
pub fn infix(self, next: Colour) -> Infix {
|
||||
Infix(self.normal(), next.normal())
|
||||
}
|
||||
|
||||
/// The suffix for this colour as a `Style`. These are the bytes that
|
||||
/// tell the terminal to reset back to its normal colour and font style.
|
||||
///
|
||||
/// See also [`Style::suffix`](struct.Style.html#method.suffix).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour::Purple;
|
||||
///
|
||||
/// assert_eq!("\x1b[0m",
|
||||
/// Purple.suffix().to_string());
|
||||
/// ```
|
||||
pub fn suffix(self) -> Suffix {
|
||||
Suffix(self.normal())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Display for Prefix {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let f: &mut fmt::Write = f;
|
||||
self.0.write_prefix(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Display for Infix {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use difference::Difference;
|
||||
|
||||
match Difference::between(&self.0, &self.1) {
|
||||
Difference::ExtraStyles(style) => {
|
||||
let f: &mut fmt::Write = f;
|
||||
style.write_prefix(f)
|
||||
},
|
||||
Difference::Reset => {
|
||||
let f: &mut fmt::Write = f;
|
||||
write!(f, "{}{}", RESET, self.1.prefix())
|
||||
},
|
||||
Difference::NoDifference => {
|
||||
Ok(()) // nothing to write
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Display for Suffix {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let f: &mut fmt::Write = f;
|
||||
self.0.write_suffix(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use style::Style;
|
||||
use style::Colour::*;
|
||||
|
||||
macro_rules! test {
|
||||
($name: ident: $style: expr; $input: expr => $result: expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
assert_eq!($style.paint($input).to_string(), $result.to_string());
|
||||
|
||||
let mut v = Vec::new();
|
||||
$style.paint($input.as_bytes()).write_to(&mut v).unwrap();
|
||||
assert_eq!(v.as_slice(), $result.as_bytes());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test!(plain: Style::default(); "text/plain" => "text/plain");
|
||||
test!(red: Red; "hi" => "\x1B[31mhi\x1B[0m");
|
||||
test!(black: Black.normal(); "hi" => "\x1B[30mhi\x1B[0m");
|
||||
test!(yellow_bold: Yellow.bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
|
||||
test!(yellow_bold_2: Yellow.normal().bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
|
||||
test!(blue_underline: Blue.underline(); "hi" => "\x1B[4;34mhi\x1B[0m");
|
||||
test!(green_bold_ul: Green.bold().underline(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
|
||||
test!(green_bold_ul_2: Green.underline().bold(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
|
||||
test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
|
||||
test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
|
||||
test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
|
||||
test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
|
||||
test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m");
|
||||
test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m");
|
||||
test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
|
||||
test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
|
||||
test!(fixed: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m");
|
||||
test!(fixed_on_purple: Fixed(100).on(Purple); "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
|
||||
test!(fixed_on_fixed: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
|
||||
test!(rgb: RGB(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
|
||||
test!(rgb_on_blue: RGB(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
|
||||
test!(blue_on_rgb: Blue.on(RGB(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
|
||||
test!(rgb_on_rgb: RGB(70,130,180).on(RGB(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
|
||||
test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m");
|
||||
test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m");
|
||||
test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m");
|
||||
test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m");
|
||||
test!(italic: Style::new().italic(); "hi" => "\x1B[3mhi\x1B[0m");
|
||||
test!(blink: Style::new().blink(); "hi" => "\x1B[5mhi\x1B[0m");
|
||||
test!(reverse: Style::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m");
|
||||
test!(hidden: Style::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m");
|
||||
test!(stricken: Style::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m");
|
||||
|
||||
#[test]
|
||||
fn test_infix() {
|
||||
assert_eq!(Style::new().dimmed().infix(Style::new()).to_string(), "\x1B[0m");
|
||||
assert_eq!(White.dimmed().infix(White.normal()).to_string(), "\x1B[0m\x1B[37m");
|
||||
assert_eq!(White.normal().infix(White.bold()).to_string(), "\x1B[1m");
|
||||
assert_eq!(White.normal().infix(Blue.normal()).to_string(), "\x1B[34m");
|
||||
assert_eq!(Blue.bold().infix(Blue.bold()).to_string(), "");
|
||||
}
|
||||
}
|
||||
134
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/debug.rs
vendored
Normal file
134
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/debug.rs
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
use std::fmt;
|
||||
|
||||
use style::Style;
|
||||
|
||||
/// Styles have a special `Debug` implementation that only shows the fields that
|
||||
/// are set. Fields that haven’t been touched aren’t included in the output.
|
||||
///
|
||||
/// This behaviour gets bypassed when using the alternate formatting mode
|
||||
/// `format!("{:#?}")`.
|
||||
///
|
||||
/// use ansi_term::Colour::{Red, Blue};
|
||||
/// assert_eq!("Style { fg(Red), on(Blue), bold, italic }",
|
||||
/// format!("{:?}", Red.on(Blue).bold().italic()));
|
||||
impl fmt::Debug for Style {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
if fmt.alternate() {
|
||||
fmt.debug_struct("Style")
|
||||
.field("foreground", &self.foreground)
|
||||
.field("background", &self.background)
|
||||
.field("blink", &self.is_blink)
|
||||
.field("bold", &self.is_bold)
|
||||
.field("dimmed", &self.is_dimmed)
|
||||
.field("hidden", &self.is_hidden)
|
||||
.field("italic", &self.is_italic)
|
||||
.field("reverse", &self.is_reverse)
|
||||
.field("strikethrough", &self.is_strikethrough)
|
||||
.field("underline", &self.is_underline)
|
||||
.finish()
|
||||
}
|
||||
else if self.is_plain() {
|
||||
fmt.write_str("Style {}")
|
||||
}
|
||||
else {
|
||||
fmt.write_str("Style { ")?;
|
||||
|
||||
let mut written_anything = false;
|
||||
|
||||
if let Some(fg) = self.foreground {
|
||||
if written_anything { fmt.write_str(", ")? }
|
||||
written_anything = true;
|
||||
write!(fmt, "fg({:?})", fg)?
|
||||
}
|
||||
|
||||
if let Some(bg) = self.background {
|
||||
if written_anything { fmt.write_str(", ")? }
|
||||
written_anything = true;
|
||||
write!(fmt, "on({:?})", bg)?
|
||||
}
|
||||
|
||||
{
|
||||
let mut write_flag = |name| {
|
||||
if written_anything { fmt.write_str(", ")? }
|
||||
written_anything = true;
|
||||
fmt.write_str(name)
|
||||
};
|
||||
|
||||
if self.is_blink { write_flag("blink")? }
|
||||
if self.is_bold { write_flag("bold")? }
|
||||
if self.is_dimmed { write_flag("dimmed")? }
|
||||
if self.is_hidden { write_flag("hidden")? }
|
||||
if self.is_italic { write_flag("italic")? }
|
||||
if self.is_reverse { write_flag("reverse")? }
|
||||
if self.is_strikethrough { write_flag("strikethrough")? }
|
||||
if self.is_underline { write_flag("underline")? }
|
||||
}
|
||||
|
||||
write!(fmt, " }}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use style::Colour::*;
|
||||
use style::Style;
|
||||
|
||||
fn style() -> Style {
|
||||
Style::new()
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
($name: ident: $obj: expr => $result: expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
assert_eq!($result, format!("{:?}", $obj));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test!(empty: style() => "Style {}");
|
||||
test!(bold: style().bold() => "Style { bold }");
|
||||
test!(italic: style().italic() => "Style { italic }");
|
||||
test!(both: style().bold().italic() => "Style { bold, italic }");
|
||||
|
||||
test!(red: Red.normal() => "Style { fg(Red) }");
|
||||
test!(redblue: Red.normal().on(RGB(3, 2, 4)) => "Style { fg(Red), on(RGB(3, 2, 4)) }");
|
||||
|
||||
test!(everything:
|
||||
Red.on(Blue).blink().bold().dimmed().hidden().italic().reverse().strikethrough().underline() =>
|
||||
"Style { fg(Red), on(Blue), blink, bold, dimmed, hidden, italic, reverse, strikethrough, underline }");
|
||||
|
||||
#[test]
|
||||
fn long_and_detailed() {
|
||||
extern crate regex;
|
||||
let expected_debug = "Style { fg(Blue), bold }";
|
||||
let expected_pretty_repat = r##"(?x)
|
||||
Style\s+\{\s+
|
||||
foreground:\s+Some\(\s+
|
||||
Blue,?\s+
|
||||
\),\s+
|
||||
background:\s+None,\s+
|
||||
blink:\s+false,\s+
|
||||
bold:\s+true,\s+
|
||||
dimmed:\s+false,\s+
|
||||
hidden:\s+false,\s+
|
||||
italic:\s+false,\s+
|
||||
reverse:\s+false,\s+
|
||||
strikethrough:\s+
|
||||
false,\s+
|
||||
underline:\s+false,?\s+
|
||||
\}"##;
|
||||
let re = regex::Regex::new(expected_pretty_repat).unwrap();
|
||||
|
||||
let style = Blue.bold();
|
||||
let style_fmt_debug = format!("{:?}", style);
|
||||
let style_fmt_pretty = format!("{:#?}", style);
|
||||
println!("style_fmt_debug:\n{}", style_fmt_debug);
|
||||
println!("style_fmt_pretty:\n{}", style_fmt_pretty);
|
||||
|
||||
assert_eq!(expected_debug, style_fmt_debug);
|
||||
assert!(re.is_match(&style_fmt_pretty));
|
||||
}
|
||||
}
|
||||
179
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/difference.rs
vendored
Normal file
179
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/difference.rs
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
use super::Style;
|
||||
|
||||
|
||||
/// When printing out one coloured string followed by another, use one of
|
||||
/// these rules to figure out which *extra* control codes need to be sent.
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
pub enum Difference {
|
||||
|
||||
/// Print out the control codes specified by this style to end up looking
|
||||
/// like the second string's styles.
|
||||
ExtraStyles(Style),
|
||||
|
||||
/// Converting between these two is impossible, so just send a reset
|
||||
/// command and then the second string's styles.
|
||||
Reset,
|
||||
|
||||
/// The before style is exactly the same as the after style, so no further
|
||||
/// control codes need to be printed.
|
||||
NoDifference,
|
||||
}
|
||||
|
||||
|
||||
impl Difference {
|
||||
|
||||
/// Compute the 'style difference' required to turn an existing style into
|
||||
/// the given, second style.
|
||||
///
|
||||
/// For example, to turn green text into green bold text, it's redundant
|
||||
/// to write a reset command then a second green+bold command, instead of
|
||||
/// just writing one bold command. This method should see that both styles
|
||||
/// use the foreground colour green, and reduce it to a single command.
|
||||
///
|
||||
/// This method returns an enum value because it's not actually always
|
||||
/// possible to turn one style into another: for example, text could be
|
||||
/// made bold and underlined, but you can't remove the bold property
|
||||
/// without also removing the underline property. So when this has to
|
||||
/// happen, this function returns None, meaning that the entire set of
|
||||
/// styles should be reset and begun again.
|
||||
pub fn between(first: &Style, next: &Style) -> Difference {
|
||||
use self::Difference::*;
|
||||
|
||||
// XXX(Havvy): This algorithm is kind of hard to replicate without
|
||||
// having the Plain/Foreground enum variants, so I'm just leaving
|
||||
// it commented out for now, and defaulting to Reset.
|
||||
|
||||
if first == next {
|
||||
return NoDifference;
|
||||
}
|
||||
|
||||
// Cannot un-bold, so must Reset.
|
||||
if first.is_bold && !next.is_bold {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
if first.is_dimmed && !next.is_dimmed {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
if first.is_italic && !next.is_italic {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
// Cannot un-underline, so must Reset.
|
||||
if first.is_underline && !next.is_underline {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
if first.is_blink && !next.is_blink {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
if first.is_reverse && !next.is_reverse {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
if first.is_hidden && !next.is_hidden {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
if first.is_strikethrough && !next.is_strikethrough {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
// Cannot go from foreground to no foreground, so must Reset.
|
||||
if first.foreground.is_some() && next.foreground.is_none() {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
// Cannot go from background to no background, so must Reset.
|
||||
if first.background.is_some() && next.background.is_none() {
|
||||
return Reset;
|
||||
}
|
||||
|
||||
let mut extra_styles = Style::default();
|
||||
|
||||
if first.is_bold != next.is_bold {
|
||||
extra_styles.is_bold = true;
|
||||
}
|
||||
|
||||
if first.is_dimmed != next.is_dimmed {
|
||||
extra_styles.is_dimmed = true;
|
||||
}
|
||||
|
||||
if first.is_italic != next.is_italic {
|
||||
extra_styles.is_italic = true;
|
||||
}
|
||||
|
||||
if first.is_underline != next.is_underline {
|
||||
extra_styles.is_underline = true;
|
||||
}
|
||||
|
||||
if first.is_blink != next.is_blink {
|
||||
extra_styles.is_blink = true;
|
||||
}
|
||||
|
||||
if first.is_reverse != next.is_reverse {
|
||||
extra_styles.is_reverse = true;
|
||||
}
|
||||
|
||||
if first.is_hidden != next.is_hidden {
|
||||
extra_styles.is_hidden = true;
|
||||
}
|
||||
|
||||
if first.is_strikethrough != next.is_strikethrough {
|
||||
extra_styles.is_strikethrough = true;
|
||||
}
|
||||
|
||||
if first.foreground != next.foreground {
|
||||
extra_styles.foreground = next.foreground;
|
||||
}
|
||||
|
||||
if first.background != next.background {
|
||||
extra_styles.background = next.background;
|
||||
}
|
||||
|
||||
ExtraStyles(extra_styles)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use super::Difference::*;
|
||||
use style::Colour::*;
|
||||
use style::Style;
|
||||
|
||||
fn style() -> Style {
|
||||
Style::new()
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
($name: ident: $first: expr; $next: expr => $result: expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
assert_eq!($result, Difference::between(&$first, &$next));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test!(nothing: Green.normal(); Green.normal() => NoDifference);
|
||||
test!(uppercase: Green.normal(); Green.bold() => ExtraStyles(style().bold()));
|
||||
test!(lowercase: Green.bold(); Green.normal() => Reset);
|
||||
test!(nothing2: Green.bold(); Green.bold() => NoDifference);
|
||||
|
||||
test!(colour_change: Red.normal(); Blue.normal() => ExtraStyles(Blue.normal()));
|
||||
|
||||
test!(addition_of_blink: style(); style().blink() => ExtraStyles(style().blink()));
|
||||
test!(addition_of_dimmed: style(); style().dimmed() => ExtraStyles(style().dimmed()));
|
||||
test!(addition_of_hidden: style(); style().hidden() => ExtraStyles(style().hidden()));
|
||||
test!(addition_of_reverse: style(); style().reverse() => ExtraStyles(style().reverse()));
|
||||
test!(addition_of_strikethrough: style(); style().strikethrough() => ExtraStyles(style().strikethrough()));
|
||||
|
||||
test!(removal_of_strikethrough: style().strikethrough(); style() => Reset);
|
||||
test!(removal_of_reverse: style().reverse(); style() => Reset);
|
||||
test!(removal_of_hidden: style().hidden(); style() => Reset);
|
||||
test!(removal_of_dimmed: style().dimmed(); style() => Reset);
|
||||
test!(removal_of_blink: style().blink(); style() => Reset);
|
||||
}
|
||||
296
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/display.rs
vendored
Normal file
296
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/display.rs
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
|
||||
use ansi::RESET;
|
||||
use difference::Difference;
|
||||
use style::{Style, Colour};
|
||||
use write::AnyWrite;
|
||||
|
||||
|
||||
/// An `ANSIGenericString` includes a generic string type and a `Style` to
|
||||
/// display that string. `ANSIString` and `ANSIByteString` are aliases for
|
||||
/// this type on `str` and `\[u8]`, respectively.
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct ANSIGenericString<'a, S: 'a + ToOwned + ?Sized>
|
||||
where <S as ToOwned>::Owned: fmt::Debug {
|
||||
style: Style,
|
||||
string: Cow<'a, S>,
|
||||
}
|
||||
|
||||
|
||||
/// Cloning an `ANSIGenericString` will clone its underlying string.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::ANSIString;
|
||||
///
|
||||
/// let plain_string = ANSIString::from("a plain string");
|
||||
/// let clone_string = plain_string.clone();
|
||||
/// assert_eq!(clone_string, plain_string);
|
||||
/// ```
|
||||
impl<'a, S: 'a + ToOwned + ?Sized> Clone for ANSIGenericString<'a, S>
|
||||
where <S as ToOwned>::Owned: fmt::Debug {
|
||||
fn clone(&self) -> ANSIGenericString<'a, S> {
|
||||
ANSIGenericString {
|
||||
style: self.style,
|
||||
string: self.string.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// You might think that the hand-written Clone impl above is the same as the
|
||||
// one that gets generated with #[derive]. But it’s not *quite* the same!
|
||||
//
|
||||
// `str` is not Clone, and the derived Clone implementation puts a Clone
|
||||
// constraint on the S type parameter (generated using --pretty=expanded):
|
||||
//
|
||||
// ↓_________________↓
|
||||
// impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone
|
||||
// for ANSIGenericString<'a, S> where
|
||||
// <S as ToOwned>::Owned: fmt::Debug { ... }
|
||||
//
|
||||
// This resulted in compile errors when you tried to derive Clone on a type
|
||||
// that used it:
|
||||
//
|
||||
// #[derive(PartialEq, Debug, Clone, Default)]
|
||||
// pub struct TextCellContents(Vec<ANSIString<'static>>);
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
|
||||
//
|
||||
// The hand-written impl above can ignore that constraint and still compile.
|
||||
|
||||
|
||||
|
||||
/// An ANSI String is a string coupled with the `Style` to display it
|
||||
/// in a terminal.
|
||||
///
|
||||
/// Although not technically a string itself, it can be turned into
|
||||
/// one with the `to_string` method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::ANSIString;
|
||||
/// use ansi_term::Colour::Red;
|
||||
///
|
||||
/// let red_string = Red.paint("a red string");
|
||||
/// println!("{}", red_string);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::ANSIString;
|
||||
///
|
||||
/// let plain_string = ANSIString::from("a plain string");
|
||||
/// assert_eq!(&*plain_string, "a plain string");
|
||||
/// ```
|
||||
pub type ANSIString<'a> = ANSIGenericString<'a, str>;
|
||||
|
||||
/// An `ANSIByteString` represents a formatted series of bytes. Use
|
||||
/// `ANSIByteString` when styling text with an unknown encoding.
|
||||
pub type ANSIByteString<'a> = ANSIGenericString<'a, [u8]>;
|
||||
|
||||
impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for ANSIGenericString<'a, S>
|
||||
where I: Into<Cow<'a, S>>,
|
||||
<S as ToOwned>::Owned: fmt::Debug {
|
||||
fn from(input: I) -> ANSIGenericString<'a, S> {
|
||||
ANSIGenericString {
|
||||
string: input.into(),
|
||||
style: Style::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
|
||||
where <S as ToOwned>::Owned: fmt::Debug {
|
||||
|
||||
/// Directly access the style
|
||||
pub fn style_ref(&self) -> &Style {
|
||||
&self.style
|
||||
}
|
||||
|
||||
/// Directly access the style mutably
|
||||
pub fn style_ref_mut(&mut self) -> &mut Style {
|
||||
&mut self.style
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + ToOwned + ?Sized> Deref for ANSIGenericString<'a, S>
|
||||
where <S as ToOwned>::Owned: fmt::Debug {
|
||||
type Target = S;
|
||||
|
||||
fn deref(&self) -> &S {
|
||||
self.string.deref()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A set of `ANSIGenericString`s collected together, in order to be
|
||||
/// written with a minimum of control characters.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ANSIGenericStrings<'a, S: 'a + ToOwned + ?Sized>
|
||||
(pub &'a [ANSIGenericString<'a, S>])
|
||||
where <S as ToOwned>::Owned: fmt::Debug, S: PartialEq;
|
||||
|
||||
/// A set of `ANSIString`s collected together, in order to be written with a
|
||||
/// minimum of control characters.
|
||||
pub type ANSIStrings<'a> = ANSIGenericStrings<'a, str>;
|
||||
|
||||
/// A function to construct an `ANSIStrings` instance.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn ANSIStrings<'a>(arg: &'a [ANSIString<'a>]) -> ANSIStrings<'a> {
|
||||
ANSIGenericStrings(arg)
|
||||
}
|
||||
|
||||
/// A set of `ANSIByteString`s collected together, in order to be
|
||||
/// written with a minimum of control characters.
|
||||
pub type ANSIByteStrings<'a> = ANSIGenericStrings<'a, [u8]>;
|
||||
|
||||
/// A function to construct an `ANSIByteStrings` instance.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn ANSIByteStrings<'a>(arg: &'a [ANSIByteString<'a>]) -> ANSIByteStrings<'a> {
|
||||
ANSIGenericStrings(arg)
|
||||
}
|
||||
|
||||
|
||||
// ---- paint functions ----
|
||||
|
||||
impl Style {
|
||||
|
||||
/// Paints the given text with this colour, returning an ANSI string.
|
||||
#[must_use]
|
||||
pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
|
||||
where I: Into<Cow<'a, S>>,
|
||||
<S as ToOwned>::Owned: fmt::Debug {
|
||||
ANSIGenericString {
|
||||
string: input.into(),
|
||||
style: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Colour {
|
||||
|
||||
/// Paints the given text with this colour, returning an ANSI string.
|
||||
/// This is a short-cut so you don’t have to use `Blue.normal()` just
|
||||
/// to get blue text.
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour::Blue;
|
||||
/// println!("{}", Blue.paint("da ba dee"));
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
|
||||
where I: Into<Cow<'a, S>>,
|
||||
<S as ToOwned>::Owned: fmt::Debug {
|
||||
ANSIGenericString {
|
||||
string: input.into(),
|
||||
style: self.normal(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- writers for individual ANSI strings ----
|
||||
|
||||
impl<'a> fmt::Display for ANSIString<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let w: &mut fmt::Write = f;
|
||||
self.write_to_any(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ANSIByteString<'a> {
|
||||
/// Write an `ANSIByteString` to an `io::Write`. This writes the escape
|
||||
/// sequences for the associated `Style` around the bytes.
|
||||
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
let w: &mut io::Write = w;
|
||||
self.write_to_any(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
|
||||
where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
|
||||
fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
|
||||
write!(w, "{}", self.style.prefix())?;
|
||||
w.write_str(self.string.as_ref())?;
|
||||
write!(w, "{}", self.style.suffix())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- writers for combined ANSI strings ----
|
||||
|
||||
impl<'a> fmt::Display for ANSIStrings<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let f: &mut fmt::Write = f;
|
||||
self.write_to_any(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ANSIByteStrings<'a> {
|
||||
/// Write `ANSIByteStrings` to an `io::Write`. This writes the minimal
|
||||
/// escape sequences for the associated `Style`s around each set of
|
||||
/// bytes.
|
||||
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
let w: &mut io::Write = w;
|
||||
self.write_to_any(w)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: 'a + ToOwned + ?Sized + PartialEq> ANSIGenericStrings<'a, S>
|
||||
where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
|
||||
fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
|
||||
use self::Difference::*;
|
||||
|
||||
let first = match self.0.first() {
|
||||
None => return Ok(()),
|
||||
Some(f) => f,
|
||||
};
|
||||
|
||||
write!(w, "{}", first.style.prefix())?;
|
||||
w.write_str(first.string.as_ref())?;
|
||||
|
||||
for window in self.0.windows(2) {
|
||||
match Difference::between(&window[0].style, &window[1].style) {
|
||||
ExtraStyles(style) => write!(w, "{}", style.prefix())?,
|
||||
Reset => write!(w, "{}{}", RESET, window[1].style.prefix())?,
|
||||
NoDifference => {/* Do nothing! */},
|
||||
}
|
||||
|
||||
w.write_str(&window[1].string)?;
|
||||
}
|
||||
|
||||
// Write the final reset string after all of the ANSIStrings have been
|
||||
// written, *except* if the last one has no styles, because it would
|
||||
// have already been written by this point.
|
||||
if let Some(last) = self.0.last() {
|
||||
if !last.style.is_plain() {
|
||||
write!(w, "{}", RESET)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- tests ----
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub use super::super::ANSIStrings;
|
||||
pub use style::Style;
|
||||
pub use style::Colour::*;
|
||||
|
||||
#[test]
|
||||
fn no_control_codes_for_plain() {
|
||||
let one = Style::default().paint("one");
|
||||
let two = Style::default().paint("two");
|
||||
let output = format!("{}", ANSIStrings( &[ one, two ] ));
|
||||
assert_eq!(&*output, "onetwo");
|
||||
}
|
||||
}
|
||||
271
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/lib.rs
vendored
Normal file
271
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/lib.rs
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
//! This is a library for controlling colours and formatting, such as
|
||||
//! red bold text or blue underlined text, on ANSI terminals.
|
||||
//!
|
||||
//!
|
||||
//! ## Basic usage
|
||||
//!
|
||||
//! There are three main types in this crate that you need to be
|
||||
//! concerned with: [`ANSIString`], [`Style`], and [`Colour`].
|
||||
//!
|
||||
//! A `Style` holds stylistic information: foreground and background colours,
|
||||
//! whether the text should be bold, or blinking, or other properties. The
|
||||
//! [`Colour`] enum represents the available colours. And an [`ANSIString`] is a
|
||||
//! string paired with a [`Style`].
|
||||
//!
|
||||
//! [`Color`] is also available as an alias to `Colour`.
|
||||
//!
|
||||
//! To format a string, call the `paint` method on a `Style` or a `Colour`,
|
||||
//! passing in the string you want to format as the argument. For example,
|
||||
//! here’s how to get some red text:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::Red;
|
||||
//!
|
||||
//! println!("This is in red: {}", Red.paint("a red string"));
|
||||
//! ```
|
||||
//!
|
||||
//! It’s important to note that the `paint` method does *not* actually return a
|
||||
//! string with the ANSI control characters surrounding it. Instead, it returns
|
||||
//! an [`ANSIString`] value that has a [`Display`] implementation that, when
|
||||
//! formatted, returns the characters. This allows strings to be printed with a
|
||||
//! minimum of [`String`] allocations being performed behind the scenes.
|
||||
//!
|
||||
//! If you *do* want to get at the escape codes, then you can convert the
|
||||
//! [`ANSIString`] to a string as you would any other `Display` value:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::Red;
|
||||
//!
|
||||
//! let red_string = Red.paint("a red string").to_string();
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! ## Bold, underline, background, and other styles
|
||||
//!
|
||||
//! For anything more complex than plain foreground colour changes, you need to
|
||||
//! construct `Style` values themselves, rather than beginning with a `Colour`.
|
||||
//! You can do this by chaining methods based on a new `Style`, created with
|
||||
//! [`Style::new()`]. Each method creates a new style that has that specific
|
||||
//! property set. For example:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Style;
|
||||
//!
|
||||
//! println!("How about some {} and {}?",
|
||||
//! Style::new().bold().paint("bold"),
|
||||
//! Style::new().underline().paint("underline"));
|
||||
//! ```
|
||||
//!
|
||||
//! For brevity, these methods have also been implemented for `Colour` values,
|
||||
//! so you can give your styles a foreground colour without having to begin with
|
||||
//! an empty `Style` value:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::{Blue, Yellow};
|
||||
//!
|
||||
//! println!("Demonstrating {} and {}!",
|
||||
//! Blue.bold().paint("blue bold"),
|
||||
//! Yellow.underline().paint("yellow underline"));
|
||||
//!
|
||||
//! println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
|
||||
//! ```
|
||||
//!
|
||||
//! The complete list of styles you can use are: [`bold`], [`dimmed`], [`italic`],
|
||||
//! [`underline`], [`blink`], [`reverse`], [`hidden`], [`strikethrough`], and [`on`] for
|
||||
//! background colours.
|
||||
//!
|
||||
//! In some cases, you may find it easier to change the foreground on an
|
||||
//! existing `Style` rather than starting from the appropriate `Colour`.
|
||||
//! You can do this using the [`fg`] method:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Style;
|
||||
//! use ansi_term::Colour::{Blue, Cyan, Yellow};
|
||||
//!
|
||||
//! println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
|
||||
//! println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
|
||||
//! ```
|
||||
//!
|
||||
//! You can turn a `Colour` into a `Style` with the [`normal`] method.
|
||||
//! This will produce the exact same `ANSIString` as if you just used the
|
||||
//! `paint` method on the `Colour` directly, but it’s useful in certain cases:
|
||||
//! for example, you may have a method that returns `Styles`, and need to
|
||||
//! represent both the “red bold” and “red, but not bold” styles with values of
|
||||
//! the same type. The `Style` struct also has a [`Default`] implementation if you
|
||||
//! want to have a style with *nothing* set.
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Style;
|
||||
//! use ansi_term::Colour::Red;
|
||||
//!
|
||||
//! Red.normal().paint("yet another red string");
|
||||
//! Style::default().paint("a completely regular string");
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! ## Extended colours
|
||||
//!
|
||||
//! You can access the extended range of 256 colours by using the `Colour::Fixed`
|
||||
//! variant, which takes an argument of the colour number to use. This can be
|
||||
//! included wherever you would use a `Colour`:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::Fixed;
|
||||
//!
|
||||
//! Fixed(134).paint("A sort of light purple");
|
||||
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
|
||||
//! ```
|
||||
//!
|
||||
//! The first sixteen of these values are the same as the normal and bold
|
||||
//! standard colour variants. There’s nothing stopping you from using these as
|
||||
//! `Fixed` colours instead, but there’s nothing to be gained by doing so
|
||||
//! either.
|
||||
//!
|
||||
//! You can also access full 24-bit colour by using the `Colour::RGB` variant,
|
||||
//! which takes separate `u8` arguments for red, green, and blue:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::RGB;
|
||||
//!
|
||||
//! RGB(70, 130, 180).paint("Steel blue");
|
||||
//! ```
|
||||
//!
|
||||
//! ## Combining successive coloured strings
|
||||
//!
|
||||
//! The benefit of writing ANSI escape codes to the terminal is that they
|
||||
//! *stack*: you do not need to end every coloured string with a reset code if
|
||||
//! the text that follows it is of a similar style. For example, if you want to
|
||||
//! have some blue text followed by some blue bold text, it’s possible to send
|
||||
//! the ANSI code for blue, followed by the ANSI code for bold, and finishing
|
||||
//! with a reset code without having to have an extra one between the two
|
||||
//! strings.
|
||||
//!
|
||||
//! This crate can optimise the ANSI codes that get printed in situations like
|
||||
//! this, making life easier for your terminal renderer. The [`ANSIStrings`]
|
||||
//! type takes a slice of several [`ANSIString`] values, and will iterate over
|
||||
//! each of them, printing only the codes for the styles that need to be updated
|
||||
//! as part of its formatting routine.
|
||||
//!
|
||||
//! The following code snippet uses this to enclose a binary number displayed in
|
||||
//! red bold text inside some red, but not bold, brackets:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::Red;
|
||||
//! use ansi_term::{ANSIString, ANSIStrings};
|
||||
//!
|
||||
//! let some_value = format!("{:b}", 42);
|
||||
//! let strings: &[ANSIString<'static>] = &[
|
||||
//! Red.paint("["),
|
||||
//! Red.bold().paint(some_value),
|
||||
//! Red.paint("]"),
|
||||
//! ];
|
||||
//!
|
||||
//! println!("Value: {}", ANSIStrings(strings));
|
||||
//! ```
|
||||
//!
|
||||
//! There are several things to note here. Firstly, the [`paint`] method can take
|
||||
//! *either* an owned [`String`] or a borrowed [`&str`]. Internally, an [`ANSIString`]
|
||||
//! holds a copy-on-write ([`Cow`]) string value to deal with both owned and
|
||||
//! borrowed strings at the same time. This is used here to display a `String`,
|
||||
//! the result of the `format!` call, using the same mechanism as some
|
||||
//! statically-available `&str` slices. Secondly, that the [`ANSIStrings`] value
|
||||
//! works in the same way as its singular counterpart, with a [`Display`]
|
||||
//! implementation that only performs the formatting when required.
|
||||
//!
|
||||
//! ## Byte strings
|
||||
//!
|
||||
//! This library also supports formatting `\[u8]` byte strings; this supports
|
||||
//! applications working with text in an unknown encoding. [`Style`] and
|
||||
//! [`Colour`] support painting `\[u8]` values, resulting in an [`ANSIByteString`].
|
||||
//! This type does not implement [`Display`], as it may not contain UTF-8, but
|
||||
//! it does provide a method [`write_to`] to write the result to any value that
|
||||
//! implements [`Write`]:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::Green;
|
||||
//!
|
||||
//! Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! Similarly, the type [`ANSIByteStrings`] supports writing a list of
|
||||
//! [`ANSIByteString`] values with minimal escape sequences:
|
||||
//!
|
||||
//! ```
|
||||
//! use ansi_term::Colour::Green;
|
||||
//! use ansi_term::ANSIByteStrings;
|
||||
//!
|
||||
//! ANSIByteStrings(&[
|
||||
//! Green.paint("user data 1\n".as_bytes()),
|
||||
//! Green.bold().paint("user data 2\n".as_bytes()),
|
||||
//! ]).write_to(&mut std::io::stdout()).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! [`Cow`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html
|
||||
//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
|
||||
//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html
|
||||
//! [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
|
||||
//! [`&str`]: https://doc.rust-lang.org/std/primitive.str.html
|
||||
//! [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
|
||||
//! [`Style`]: struct.Style.html
|
||||
//! [`Style::new()`]: struct.Style.html#method.new
|
||||
//! [`Color`]: enum.Color.html
|
||||
//! [`Colour`]: enum.Colour.html
|
||||
//! [`ANSIString`]: type.ANSIString.html
|
||||
//! [`ANSIStrings`]: type.ANSIStrings.html
|
||||
//! [`ANSIByteString`]: type.ANSIByteString.html
|
||||
//! [`ANSIByteStrings`]: type.ANSIByteStrings.html
|
||||
//! [`write_to`]: type.ANSIByteString.html#method.write_to
|
||||
//! [`paint`]: type.ANSIByteString.html#method.write_to
|
||||
//! [`normal`]: enum.Colour.html#method.normal
|
||||
//!
|
||||
//! [`bold`]: struct.Style.html#method.bold
|
||||
//! [`dimmed`]: struct.Style.html#method.dimmed
|
||||
//! [`italic`]: struct.Style.html#method.italic
|
||||
//! [`underline`]: struct.Style.html#method.underline
|
||||
//! [`blink`]: struct.Style.html#method.blink
|
||||
//! [`reverse`]: struct.Style.html#method.reverse
|
||||
//! [`hidden`]: struct.Style.html#method.hidden
|
||||
//! [`strikethrough`]: struct.Style.html#method.strikethrough
|
||||
//! [`fg`]: struct.Style.html#method.fg
|
||||
//! [`on`]: struct.Style.html#method.on
|
||||
|
||||
#![crate_name = "ansi_term"]
|
||||
#![crate_type = "rlib"]
|
||||
#![crate_type = "dylib"]
|
||||
|
||||
#![warn(missing_copy_implementations)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(trivial_casts, trivial_numeric_casts)]
|
||||
#![warn(unused_extern_crates, unused_qualifications)]
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
extern crate winapi;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate doc_comment;
|
||||
|
||||
#[cfg(test)]
|
||||
doctest!("../README.md");
|
||||
|
||||
mod ansi;
|
||||
pub use ansi::{Prefix, Infix, Suffix};
|
||||
|
||||
mod style;
|
||||
pub use style::{Colour, Style};
|
||||
|
||||
/// Color is a type alias for `Colour`.
|
||||
pub use Colour as Color;
|
||||
|
||||
mod difference;
|
||||
mod display;
|
||||
pub use display::*;
|
||||
|
||||
mod write;
|
||||
|
||||
mod windows;
|
||||
pub use windows::*;
|
||||
|
||||
mod util;
|
||||
pub use util::*;
|
||||
|
||||
mod debug;
|
||||
521
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/style.rs
vendored
Normal file
521
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/style.rs
vendored
Normal file
@@ -0,0 +1,521 @@
|
||||
/// A style is a collection of properties that can format a string
|
||||
/// using ANSI escape codes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour};
|
||||
///
|
||||
/// let style = Style::new().bold().on(Colour::Black);
|
||||
/// println!("{}", style.paint("Bold on black"));
|
||||
/// ```
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
#[cfg_attr(feature = "derive_serde_style", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct Style {
|
||||
|
||||
/// The style's foreground colour, if it has one.
|
||||
pub foreground: Option<Colour>,
|
||||
|
||||
/// The style's background colour, if it has one.
|
||||
pub background: Option<Colour>,
|
||||
|
||||
/// Whether this style is bold.
|
||||
pub is_bold: bool,
|
||||
|
||||
/// Whether this style is dimmed.
|
||||
pub is_dimmed: bool,
|
||||
|
||||
/// Whether this style is italic.
|
||||
pub is_italic: bool,
|
||||
|
||||
/// Whether this style is underlined.
|
||||
pub is_underline: bool,
|
||||
|
||||
/// Whether this style is blinking.
|
||||
pub is_blink: bool,
|
||||
|
||||
/// Whether this style has reverse colours.
|
||||
pub is_reverse: bool,
|
||||
|
||||
/// Whether this style is hidden.
|
||||
pub is_hidden: bool,
|
||||
|
||||
/// Whether this style is struckthrough.
|
||||
pub is_strikethrough: bool
|
||||
}
|
||||
|
||||
impl Style {
|
||||
|
||||
/// Creates a new Style with no properties set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new();
|
||||
/// println!("{}", style.paint("hi"));
|
||||
/// ```
|
||||
pub fn new() -> Style {
|
||||
Style::default()
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the bold property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().bold();
|
||||
/// println!("{}", style.paint("hey"));
|
||||
/// ```
|
||||
pub fn bold(&self) -> Style {
|
||||
Style { is_bold: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the dimmed property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().dimmed();
|
||||
/// println!("{}", style.paint("sup"));
|
||||
/// ```
|
||||
pub fn dimmed(&self) -> Style {
|
||||
Style { is_dimmed: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the italic property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().italic();
|
||||
/// println!("{}", style.paint("greetings"));
|
||||
/// ```
|
||||
pub fn italic(&self) -> Style {
|
||||
Style { is_italic: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the underline property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().underline();
|
||||
/// println!("{}", style.paint("salutations"));
|
||||
/// ```
|
||||
pub fn underline(&self) -> Style {
|
||||
Style { is_underline: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the blink property set.
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().blink();
|
||||
/// println!("{}", style.paint("wazzup"));
|
||||
/// ```
|
||||
pub fn blink(&self) -> Style {
|
||||
Style { is_blink: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the reverse property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().reverse();
|
||||
/// println!("{}", style.paint("aloha"));
|
||||
/// ```
|
||||
pub fn reverse(&self) -> Style {
|
||||
Style { is_reverse: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the hidden property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().hidden();
|
||||
/// println!("{}", style.paint("ahoy"));
|
||||
/// ```
|
||||
pub fn hidden(&self) -> Style {
|
||||
Style { is_hidden: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the strikethrough property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// let style = Style::new().strikethrough();
|
||||
/// println!("{}", style.paint("yo"));
|
||||
/// ```
|
||||
pub fn strikethrough(&self) -> Style {
|
||||
Style { is_strikethrough: true, .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour};
|
||||
///
|
||||
/// let style = Style::new().fg(Colour::Yellow);
|
||||
/// println!("{}", style.paint("hi"));
|
||||
/// ```
|
||||
pub fn fg(&self, foreground: Colour) -> Style {
|
||||
Style { foreground: Some(foreground), .. *self }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the background colour property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour};
|
||||
///
|
||||
/// let style = Style::new().on(Colour::Blue);
|
||||
/// println!("{}", style.paint("eyyyy"));
|
||||
/// ```
|
||||
pub fn on(&self, background: Colour) -> Style {
|
||||
Style { background: Some(background), .. *self }
|
||||
}
|
||||
|
||||
/// Return true if this `Style` has no actual styles, and can be written
|
||||
/// without any control characters.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
///
|
||||
/// assert_eq!(true, Style::default().is_plain());
|
||||
/// assert_eq!(false, Style::default().bold().is_plain());
|
||||
/// ```
|
||||
pub fn is_plain(self) -> bool {
|
||||
self == Style::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Style {
|
||||
|
||||
/// Returns a style with *no* properties set. Formatting text using this
|
||||
/// style returns the exact same text.
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Style;
|
||||
/// assert_eq!(None, Style::default().foreground);
|
||||
/// assert_eq!(None, Style::default().background);
|
||||
/// assert_eq!(false, Style::default().is_bold);
|
||||
/// assert_eq!("txt", Style::default().paint("txt").to_string());
|
||||
/// ```
|
||||
fn default() -> Style {
|
||||
Style {
|
||||
foreground: None,
|
||||
background: None,
|
||||
is_bold: false,
|
||||
is_dimmed: false,
|
||||
is_italic: false,
|
||||
is_underline: false,
|
||||
is_blink: false,
|
||||
is_reverse: false,
|
||||
is_hidden: false,
|
||||
is_strikethrough: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- colours ----
|
||||
|
||||
/// A colour is one specific type of ANSI escape code, and can refer
|
||||
/// to either the foreground or background colour.
|
||||
///
|
||||
/// These use the standard numeric sequences.
|
||||
/// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "derive_serde_style", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub enum Colour {
|
||||
|
||||
/// Colour #0 (foreground code `30`, background code `40`).
|
||||
///
|
||||
/// This is not necessarily the background colour, and using it as one may
|
||||
/// render the text hard to read on terminals with dark backgrounds.
|
||||
Black,
|
||||
|
||||
/// Colour #1 (foreground code `31`, background code `41`).
|
||||
Red,
|
||||
|
||||
/// Colour #2 (foreground code `32`, background code `42`).
|
||||
Green,
|
||||
|
||||
/// Colour #3 (foreground code `33`, background code `43`).
|
||||
Yellow,
|
||||
|
||||
/// Colour #4 (foreground code `34`, background code `44`).
|
||||
Blue,
|
||||
|
||||
/// Colour #5 (foreground code `35`, background code `45`).
|
||||
Purple,
|
||||
|
||||
/// Colour #6 (foreground code `36`, background code `46`).
|
||||
Cyan,
|
||||
|
||||
/// Colour #7 (foreground code `37`, background code `47`).
|
||||
///
|
||||
/// As above, this is not necessarily the foreground colour, and may be
|
||||
/// hard to read on terminals with light backgrounds.
|
||||
White,
|
||||
|
||||
/// A colour number from 0 to 255, for use in 256-colour terminal
|
||||
/// environments.
|
||||
///
|
||||
/// - Colours 0 to 7 are the `Black` to `White` variants respectively.
|
||||
/// These colours can usually be changed in the terminal emulator.
|
||||
/// - Colours 8 to 15 are brighter versions of the eight colours above.
|
||||
/// These can also usually be changed in the terminal emulator, or it
|
||||
/// could be configured to use the original colours and show the text in
|
||||
/// bold instead. It varies depending on the program.
|
||||
/// - Colours 16 to 231 contain several palettes of bright colours,
|
||||
/// arranged in six squares measuring six by six each.
|
||||
/// - Colours 232 to 255 are shades of grey from black to white.
|
||||
///
|
||||
/// It might make more sense to look at a [colour chart][cc].
|
||||
///
|
||||
/// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
|
||||
Fixed(u8),
|
||||
|
||||
/// A 24-bit RGB color, as specified by ISO-8613-3.
|
||||
RGB(u8, u8, u8),
|
||||
}
|
||||
|
||||
|
||||
impl Colour {
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Red.normal();
|
||||
/// println!("{}", style.paint("hi"));
|
||||
/// ```
|
||||
pub fn normal(self) -> Style {
|
||||
Style { foreground: Some(self), .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// bold property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Green.bold();
|
||||
/// println!("{}", style.paint("hey"));
|
||||
/// ```
|
||||
pub fn bold(self) -> Style {
|
||||
Style { foreground: Some(self), is_bold: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// dimmed property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Yellow.dimmed();
|
||||
/// println!("{}", style.paint("sup"));
|
||||
/// ```
|
||||
pub fn dimmed(self) -> Style {
|
||||
Style { foreground: Some(self), is_dimmed: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// italic property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Blue.italic();
|
||||
/// println!("{}", style.paint("greetings"));
|
||||
/// ```
|
||||
pub fn italic(self) -> Style {
|
||||
Style { foreground: Some(self), is_italic: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// underline property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Purple.underline();
|
||||
/// println!("{}", style.paint("salutations"));
|
||||
/// ```
|
||||
pub fn underline(self) -> Style {
|
||||
Style { foreground: Some(self), is_underline: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// blink property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Cyan.blink();
|
||||
/// println!("{}", style.paint("wazzup"));
|
||||
/// ```
|
||||
pub fn blink(self) -> Style {
|
||||
Style { foreground: Some(self), is_blink: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// reverse property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Black.reverse();
|
||||
/// println!("{}", style.paint("aloha"));
|
||||
/// ```
|
||||
pub fn reverse(self) -> Style {
|
||||
Style { foreground: Some(self), is_reverse: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// hidden property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::White.hidden();
|
||||
/// println!("{}", style.paint("ahoy"));
|
||||
/// ```
|
||||
pub fn hidden(self) -> Style {
|
||||
Style { foreground: Some(self), is_hidden: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// strikethrough property set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::Fixed(244).strikethrough();
|
||||
/// println!("{}", style.paint("yo"));
|
||||
/// ```
|
||||
pub fn strikethrough(self) -> Style {
|
||||
Style { foreground: Some(self), is_strikethrough: true, .. Style::default() }
|
||||
}
|
||||
|
||||
/// Returns a `Style` with the foreground colour set to this colour and the
|
||||
/// background colour property set to the given colour.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::Colour;
|
||||
///
|
||||
/// let style = Colour::RGB(31, 31, 31).on(Colour::White);
|
||||
/// println!("{}", style.paint("eyyyy"));
|
||||
/// ```
|
||||
pub fn on(self, background: Colour) -> Style {
|
||||
Style { foreground: Some(self), background: Some(background), .. Style::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Colour> for Style {
|
||||
|
||||
/// You can turn a `Colour` into a `Style` with the foreground colour set
|
||||
/// with the `From` trait.
|
||||
///
|
||||
/// ```
|
||||
/// use ansi_term::{Style, Colour};
|
||||
/// let green_foreground = Style::default().fg(Colour::Green);
|
||||
/// assert_eq!(green_foreground, Colour::Green.normal());
|
||||
/// assert_eq!(green_foreground, Colour::Green.into());
|
||||
/// assert_eq!(green_foreground, Style::from(Colour::Green));
|
||||
/// ```
|
||||
fn from(colour: Colour) -> Style {
|
||||
colour.normal()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "derive_serde_style")]
|
||||
mod serde_json_tests {
|
||||
use super::{Style, Colour};
|
||||
|
||||
#[test]
|
||||
fn colour_serialization() {
|
||||
|
||||
let colours = &[
|
||||
Colour::Red,
|
||||
Colour::Blue,
|
||||
Colour::RGB(123, 123, 123),
|
||||
Colour::Fixed(255),
|
||||
];
|
||||
|
||||
assert_eq!(serde_json::to_string(&colours).unwrap(), String::from("[\"Red\",\"Blue\",{\"RGB\":[123,123,123]},{\"Fixed\":255}]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colour_deserialization() {
|
||||
let colours = &[
|
||||
Colour::Red,
|
||||
Colour::Blue,
|
||||
Colour::RGB(123, 123, 123),
|
||||
Colour::Fixed(255),
|
||||
];
|
||||
|
||||
for colour in colours.into_iter() {
|
||||
let serialized = serde_json::to_string(&colour).unwrap();
|
||||
let deserialized: Colour = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(colour, &deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn style_serialization() {
|
||||
let style = Style::default();
|
||||
|
||||
assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
|
||||
}
|
||||
}
|
||||
81
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/util.rs
vendored
Normal file
81
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/util.rs
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
use display::*;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Return a substring of the given ANSIStrings sequence, while keeping the formatting.
|
||||
pub fn sub_string<'a>(start: usize, len: usize, strs: &ANSIStrings<'a>) -> Vec<ANSIString<'static>> {
|
||||
let mut vec = Vec::new();
|
||||
let mut pos = start;
|
||||
let mut len_rem = len;
|
||||
|
||||
for i in strs.0.iter() {
|
||||
let fragment = i.deref();
|
||||
let frag_len = fragment.len();
|
||||
if pos >= frag_len {
|
||||
pos -= frag_len;
|
||||
continue;
|
||||
}
|
||||
if len_rem <= 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let end = pos + len_rem;
|
||||
let pos_end = if end >= frag_len { frag_len } else { end };
|
||||
|
||||
vec.push(i.style_ref().paint(String::from(&fragment[pos..pos_end])));
|
||||
|
||||
if end <= frag_len {
|
||||
break;
|
||||
}
|
||||
|
||||
len_rem -= pos_end - pos;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
/// Return a concatenated copy of `strs` without the formatting, as an allocated `String`.
|
||||
pub fn unstyle(strs: &ANSIStrings) -> String {
|
||||
let mut s = String::new();
|
||||
|
||||
for i in strs.0.iter() {
|
||||
s += &i.deref();
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
/// Return the unstyled length of ANSIStrings. This is equaivalent to `unstyle(strs).len()`.
|
||||
pub fn unstyled_len(strs: &ANSIStrings) -> usize {
|
||||
let mut l = 0;
|
||||
for i in strs.0.iter() {
|
||||
l += i.deref().len();
|
||||
}
|
||||
l
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use Colour::*;
|
||||
use display::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let l = [
|
||||
Black.paint("first"),
|
||||
Red.paint("-second"),
|
||||
White.paint("-third"),
|
||||
];
|
||||
let a = ANSIStrings(&l);
|
||||
assert_eq!(unstyle(&a), "first-second-third");
|
||||
assert_eq!(unstyled_len(&a), 18);
|
||||
|
||||
let l2 = [
|
||||
Black.paint("st"),
|
||||
Red.paint("-second"),
|
||||
White.paint("-t"),
|
||||
];
|
||||
assert_eq!(sub_string(3, 11, &a).as_slice(), &l2);
|
||||
}
|
||||
}
|
||||
61
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/windows.rs
vendored
Normal file
61
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/windows.rs
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/// Enables ANSI code support on Windows 10.
|
||||
///
|
||||
/// This uses Windows API calls to alter the properties of the console that
|
||||
/// the program is running in.
|
||||
///
|
||||
/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx
|
||||
///
|
||||
/// Returns a `Result` with the Windows error code if unsuccessful.
|
||||
#[cfg(windows)]
|
||||
pub fn enable_ansi_support() -> Result<(), u32> {
|
||||
// ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76%
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::iter::once;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::ptr::null_mut;
|
||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
|
||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||
use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
|
||||
|
||||
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004;
|
||||
|
||||
unsafe {
|
||||
// ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
// Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
|
||||
let console_out_name: Vec<u16> = OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect();
|
||||
let console_handle = CreateFileW(
|
||||
console_out_name.as_ptr(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
null_mut(),
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
null_mut(),
|
||||
);
|
||||
if console_handle == INVALID_HANDLE_VALUE
|
||||
{
|
||||
return Err(GetLastError());
|
||||
}
|
||||
|
||||
// ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
|
||||
let mut console_mode: u32 = 0;
|
||||
if 0 == GetConsoleMode(console_handle, &mut console_mode)
|
||||
{
|
||||
return Err(GetLastError());
|
||||
}
|
||||
|
||||
// VT processing not already enabled?
|
||||
if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
|
||||
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
|
||||
if 0 == SetConsoleMode(console_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
{
|
||||
return Err(GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
40
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/write.rs
vendored
Normal file
40
clamav/libclamav_rust/.cargo/vendor/ansi_term/src/write.rs
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
|
||||
pub trait AnyWrite {
|
||||
type wstr: ?Sized;
|
||||
type Error;
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error>;
|
||||
|
||||
fn write_str(&mut self, s: &Self::wstr) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
|
||||
impl<'a> AnyWrite for fmt::Write + 'a {
|
||||
type wstr = str;
|
||||
type Error = fmt::Error;
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
|
||||
fmt::Write::write_fmt(self, fmt)
|
||||
}
|
||||
|
||||
fn write_str(&mut self, s: &Self::wstr) -> Result<(), Self::Error> {
|
||||
fmt::Write::write_str(self, s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> AnyWrite for io::Write + 'a {
|
||||
type wstr = [u8];
|
||||
type Error = io::Error;
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
|
||||
io::Write::write_fmt(self, fmt)
|
||||
}
|
||||
|
||||
fn write_str(&mut self, s: &Self::wstr) -> Result<(), Self::Error> {
|
||||
io::Write::write_all(self, s)
|
||||
}
|
||||
}
|
||||
1
clamav/libclamav_rust/.cargo/vendor/atty/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/atty/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"CHANGELOG.md":"70db121262d72acc472ad1a90b78c42de570820e65b566c6b9339b62e636d572","Cargo.lock":"6868f02a96413bcba37a06f01c6bf87e6331dea9461681a47a561cec6acd2546","Cargo.toml":"3af88a07af6a4adb84373fc3cd4920884b0b12b338cdb55ef598fd512ee1a790","LICENSE":"99fa95ba4e4cdaf71c27d73260ea069fc4515b3d02fde3020c5b562280006cbc","README.md":"e559a69c0b2bd20bffcede64fd548df6c671b0d1504613c5e3e5d884d759caea","examples/atty.rs":"1551387a71474d9ac1b5153231f884e9e05213badcfaa3494ad2cb7ea958374a","rustfmt.toml":"8e6ea1bcb79c505490034020c98e9b472f4ac4113f245bae90f5e1217b1ec65a","src/lib.rs":"d5abf6a54e8c496c486572bdc91eef10480f6ad126c4287f039df5feff7a9bbb"},"package":"d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"}
|
||||
73
clamav/libclamav_rust/.cargo/vendor/atty/CHANGELOG.md
vendored
Normal file
73
clamav/libclamav_rust/.cargo/vendor/atty/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# 0.2.14
|
||||
|
||||
* add support for [RustyHermit](https://github.com/hermitcore/libhermit-rs), a Rust-based unikernel [#41](https://github.com/softprops/atty/pull/41)
|
||||
|
||||
# 0.2.13
|
||||
|
||||
* support older versions of rust that do now support 2018 edition
|
||||
|
||||
# 0.2.12
|
||||
|
||||
* Redox is now in the unix family so redox cfg is no longer needed [#35](https://github.com/softprops/atty/pull/35)
|
||||
|
||||
# 0.2.11
|
||||
|
||||
* fix msys detection with `winapi@0.3.5` [#28](https://github.com/softprops/atty/pull/28)
|
||||
|
||||
# 0.2.10
|
||||
|
||||
* fix wasm regression [#27](https://github.com/softprops/atty/pull/27)
|
||||
|
||||
# 0.2.9
|
||||
|
||||
* Fix fix pty detection [#25](https://github.com/softprops/atty/pull/25)
|
||||
|
||||
# 0.2.8
|
||||
|
||||
* Fix an inverted condition on MinGW [#22](https://github.com/softprops/atty/pull/22)
|
||||
|
||||
# 0.2.7
|
||||
|
||||
* Change `||` to `&&` for whether MSYS is a tty [#24](https://github.com/softprops/atty/pull/24/)
|
||||
|
||||
# 0.2.6
|
||||
|
||||
* updated winapi dependency to [0.3](https://retep998.github.io/blog/winapi-0.3/) [#18](https://github.com/softprops/atty/pull/18)
|
||||
|
||||
# 0.2.5
|
||||
|
||||
* added support for Wasm compile targets [#17](https://github.com/softprops/atty/pull/17)
|
||||
|
||||
# 0.2.4
|
||||
|
||||
* added support for Wasm compile targets [#17](https://github.com/softprops/atty/pull/17)
|
||||
|
||||
# 0.2.3
|
||||
|
||||
* added support for Redox OS [#14](https://github.com/softprops/atty/pull/14)
|
||||
|
||||
# 0.2.2
|
||||
|
||||
* use target specific dependencies [#11](https://github.com/softprops/atty/pull/11)
|
||||
* Add tty detection for MSYS terminals [#12](https://github.com/softprops/atty/pull/12)
|
||||
|
||||
# 0.2.1
|
||||
|
||||
* fix windows bug
|
||||
|
||||
# 0.2.0
|
||||
|
||||
* support for various stream types
|
||||
|
||||
# 0.1.2
|
||||
|
||||
* windows support (with automated testing)
|
||||
* automated code coverage
|
||||
|
||||
# 0.1.1
|
||||
|
||||
* bumped libc dep from `0.1` to `0.2`
|
||||
|
||||
# 0.1.0
|
||||
|
||||
* initial release
|
||||
49
clamav/libclamav_rust/.cargo/vendor/atty/Cargo.lock
generated
vendored
Normal file
49
clamav/libclamav_rust/.cargo/vendor/atty/Cargo.lock
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
34
clamav/libclamav_rust/.cargo/vendor/atty/Cargo.toml
vendored
Normal file
34
clamav/libclamav_rust/.cargo/vendor/atty/Cargo.toml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# 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 = "atty"
|
||||
version = "0.2.14"
|
||||
authors = ["softprops <d.tangren@gmail.com>"]
|
||||
exclude = ["/.travis.yml", "/appveyor.yml"]
|
||||
description = "A simple interface for querying atty"
|
||||
homepage = "https://github.com/softprops/atty"
|
||||
documentation = "http://softprops.github.io/atty"
|
||||
readme = "README.md"
|
||||
keywords = ["terminal", "tty", "isatty"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/softprops/atty"
|
||||
[target."cfg(target_os = \"hermit\")".dependencies.hermit-abi]
|
||||
version = "0.1.6"
|
||||
[target."cfg(unix)".dependencies.libc]
|
||||
version = "0.2"
|
||||
default-features = false
|
||||
[target."cfg(windows)".dependencies.winapi]
|
||||
version = "0.3"
|
||||
features = ["consoleapi", "processenv", "minwinbase", "minwindef", "winbase"]
|
||||
[badges.travis-ci]
|
||||
repository = "softprops/atty"
|
||||
20
clamav/libclamav_rust/.cargo/vendor/atty/LICENSE
vendored
Normal file
20
clamav/libclamav_rust/.cargo/vendor/atty/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2015-2019 Doug Tangren
|
||||
|
||||
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.
|
||||
74
clamav/libclamav_rust/.cargo/vendor/atty/README.md
vendored
Normal file
74
clamav/libclamav_rust/.cargo/vendor/atty/README.md
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# atty
|
||||
|
||||
[](https://travis-ci.org/softprops/atty) [](https://ci.appveyor.com/project/softprops/atty) [](https://coveralls.io/github/softprops/atty?branch=master) [](https://crates.io/crates/atty) [](http://docs.rs/atty) [](https://softprops.github.io/atty)
|
||||
|
||||
> are you or are you not a tty?
|
||||
|
||||
|
||||
## install
|
||||
|
||||
Add the following to your `Cargo.toml`
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
atty = "0.2"
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
```rust
|
||||
use atty::Stream;
|
||||
|
||||
fn main() {
|
||||
if atty::is(Stream::Stdout) {
|
||||
println!("I'm a terminal");
|
||||
} else {
|
||||
println!("I'm not");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## testing
|
||||
|
||||
This library has been unit tested on both unix and windows platforms (via appveyor).
|
||||
|
||||
|
||||
A simple example program is provided in this repo to test various tty's. By default.
|
||||
|
||||
It prints
|
||||
|
||||
```bash
|
||||
$ cargo run --example atty
|
||||
stdout? true
|
||||
stderr? true
|
||||
stdin? true
|
||||
```
|
||||
|
||||
To test std in, pipe some text to the program
|
||||
|
||||
```bash
|
||||
$ echo "test" | cargo run --example atty
|
||||
stdout? true
|
||||
stderr? true
|
||||
stdin? false
|
||||
```
|
||||
|
||||
To test std out, pipe the program to something
|
||||
|
||||
```bash
|
||||
$ cargo run --example atty | grep std
|
||||
stdout? false
|
||||
stderr? true
|
||||
stdin? true
|
||||
```
|
||||
|
||||
To test std err, pipe the program to something redirecting std err
|
||||
|
||||
```bash
|
||||
$ cargo run --example atty 2>&1 | grep std
|
||||
stdout? false
|
||||
stderr? false
|
||||
stdin? true
|
||||
```
|
||||
|
||||
Doug Tangren (softprops) 2015-2019
|
||||
9
clamav/libclamav_rust/.cargo/vendor/atty/examples/atty.rs
vendored
Normal file
9
clamav/libclamav_rust/.cargo/vendor/atty/examples/atty.rs
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
extern crate atty;
|
||||
|
||||
use atty::{is, Stream};
|
||||
|
||||
fn main() {
|
||||
println!("stdout? {}", is(Stream::Stdout));
|
||||
println!("stderr? {}", is(Stream::Stderr));
|
||||
println!("stdin? {}", is(Stream::Stdin));
|
||||
}
|
||||
4
clamav/libclamav_rust/.cargo/vendor/atty/rustfmt.toml
vendored
Normal file
4
clamav/libclamav_rust/.cargo/vendor/atty/rustfmt.toml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#fn_args_layout
|
||||
fn_args_layout = "Vertical"
|
||||
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#merge_imports
|
||||
merge_imports = true
|
||||
210
clamav/libclamav_rust/.cargo/vendor/atty/src/lib.rs
vendored
Normal file
210
clamav/libclamav_rust/.cargo/vendor/atty/src/lib.rs
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
//! atty is a simple utility that answers one question
|
||||
//! > is this a tty?
|
||||
//!
|
||||
//! usage is just as simple
|
||||
//!
|
||||
//! ```
|
||||
//! if atty::is(atty::Stream::Stdout) {
|
||||
//! println!("i'm a tty")
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ```
|
||||
//! if atty::isnt(atty::Stream::Stdout) {
|
||||
//! println!("i'm not a tty")
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(unix, no_std)]
|
||||
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
#[cfg(windows)]
|
||||
extern crate winapi;
|
||||
|
||||
#[cfg(windows)]
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
#[cfg(windows)]
|
||||
use winapi::shared::ntdef::WCHAR;
|
||||
|
||||
/// possible stream sources
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Stream {
|
||||
Stdout,
|
||||
Stderr,
|
||||
Stdin,
|
||||
}
|
||||
|
||||
/// returns true if this is a tty
|
||||
#[cfg(all(unix, not(target_arch = "wasm32")))]
|
||||
pub fn is(stream: Stream) -> bool {
|
||||
extern crate libc;
|
||||
|
||||
let fd = match stream {
|
||||
Stream::Stdout => libc::STDOUT_FILENO,
|
||||
Stream::Stderr => libc::STDERR_FILENO,
|
||||
Stream::Stdin => libc::STDIN_FILENO,
|
||||
};
|
||||
unsafe { libc::isatty(fd) != 0 }
|
||||
}
|
||||
|
||||
/// returns true if this is a tty
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub fn is(stream: Stream) -> bool {
|
||||
extern crate hermit_abi;
|
||||
|
||||
let fd = match stream {
|
||||
Stream::Stdout => hermit_abi::STDOUT_FILENO,
|
||||
Stream::Stderr => hermit_abi::STDERR_FILENO,
|
||||
Stream::Stdin => hermit_abi::STDIN_FILENO,
|
||||
};
|
||||
hermit_abi::isatty(fd)
|
||||
}
|
||||
|
||||
/// returns true if this is a tty
|
||||
#[cfg(windows)]
|
||||
pub fn is(stream: Stream) -> bool {
|
||||
use winapi::um::winbase::{
|
||||
STD_ERROR_HANDLE as STD_ERROR, STD_INPUT_HANDLE as STD_INPUT,
|
||||
STD_OUTPUT_HANDLE as STD_OUTPUT,
|
||||
};
|
||||
|
||||
let (fd, others) = match stream {
|
||||
Stream::Stdin => (STD_INPUT, [STD_ERROR, STD_OUTPUT]),
|
||||
Stream::Stderr => (STD_ERROR, [STD_INPUT, STD_OUTPUT]),
|
||||
Stream::Stdout => (STD_OUTPUT, [STD_INPUT, STD_ERROR]),
|
||||
};
|
||||
if unsafe { console_on_any(&[fd]) } {
|
||||
// False positives aren't possible. If we got a console then
|
||||
// we definitely have a tty on stdin.
|
||||
return true;
|
||||
}
|
||||
|
||||
// At this point, we *could* have a false negative. We can determine that
|
||||
// this is true negative if we can detect the presence of a console on
|
||||
// any of the other streams. If another stream has a console, then we know
|
||||
// we're in a Windows console and can therefore trust the negative.
|
||||
if unsafe { console_on_any(&others) } {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we fall back to a very strange msys hack to see if we can
|
||||
// sneakily detect the presence of a tty.
|
||||
unsafe { msys_tty_on(fd) }
|
||||
}
|
||||
|
||||
/// returns true if this is _not_ a tty
|
||||
pub fn isnt(stream: Stream) -> bool {
|
||||
!is(stream)
|
||||
}
|
||||
|
||||
/// Returns true if any of the given fds are on a console.
|
||||
#[cfg(windows)]
|
||||
unsafe fn console_on_any(fds: &[DWORD]) -> bool {
|
||||
use winapi::um::{consoleapi::GetConsoleMode, processenv::GetStdHandle};
|
||||
|
||||
for &fd in fds {
|
||||
let mut out = 0;
|
||||
let handle = GetStdHandle(fd);
|
||||
if GetConsoleMode(handle, &mut out) != 0 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if there is an MSYS tty on the given handle.
|
||||
#[cfg(windows)]
|
||||
unsafe fn msys_tty_on(fd: DWORD) -> bool {
|
||||
use std::{mem, slice};
|
||||
|
||||
use winapi::{
|
||||
ctypes::c_void,
|
||||
shared::minwindef::MAX_PATH,
|
||||
um::{
|
||||
fileapi::FILE_NAME_INFO, minwinbase::FileNameInfo, processenv::GetStdHandle,
|
||||
winbase::GetFileInformationByHandleEx,
|
||||
},
|
||||
};
|
||||
|
||||
let size = mem::size_of::<FILE_NAME_INFO>();
|
||||
let mut name_info_bytes = vec![0u8; size + MAX_PATH * mem::size_of::<WCHAR>()];
|
||||
let res = GetFileInformationByHandleEx(
|
||||
GetStdHandle(fd),
|
||||
FileNameInfo,
|
||||
&mut *name_info_bytes as *mut _ as *mut c_void,
|
||||
name_info_bytes.len() as u32,
|
||||
);
|
||||
if res == 0 {
|
||||
return false;
|
||||
}
|
||||
let name_info: &FILE_NAME_INFO = &*(name_info_bytes.as_ptr() as *const FILE_NAME_INFO);
|
||||
let s = slice::from_raw_parts(
|
||||
name_info.FileName.as_ptr(),
|
||||
name_info.FileNameLength as usize / 2,
|
||||
);
|
||||
let name = String::from_utf16_lossy(s);
|
||||
// This checks whether 'pty' exists in the file name, which indicates that
|
||||
// a pseudo-terminal is attached. To mitigate against false positives
|
||||
// (e.g., an actual file name that contains 'pty'), we also require that
|
||||
// either the strings 'msys-' or 'cygwin-' are in the file name as well.)
|
||||
let is_msys = name.contains("msys-") || name.contains("cygwin-");
|
||||
let is_pty = name.contains("-pty");
|
||||
is_msys && is_pty
|
||||
}
|
||||
|
||||
/// returns true if this is a tty
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn is(_stream: Stream) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{is, Stream};
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn is_err() {
|
||||
// appveyor pipes its output
|
||||
assert!(!is(Stream::Stderr))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn is_out() {
|
||||
// appveyor pipes its output
|
||||
assert!(!is(Stream::Stdout))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn is_in() {
|
||||
assert!(is(Stream::Stdin))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn is_err() {
|
||||
assert!(is(Stream::Stderr))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn is_out() {
|
||||
assert!(is(Stream::Stdout))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn is_in() {
|
||||
// macos on travis seems to pipe its input
|
||||
assert!(is(Stream::Stdin))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(not(target_os = "macos"), unix))]
|
||||
fn is_in() {
|
||||
assert!(is(Stream::Stdin))
|
||||
}
|
||||
}
|
||||
1
clamav/libclamav_rust/.cargo/vendor/autocfg/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/autocfg/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"Cargo.lock":"3d91565ed13de572a9ebde408a0c98e33f931d6ab52f212b0830a60b4ab26b77","Cargo.toml":"39f627122dceaad42146634719fde802fca3baa1b3908753af723074ae2a6d69","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"4c8f9b5016f2a0c3dbeca5bc41241f57db5568f803e58c1fa480ae2b3638d0a9","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"6fa01458e8f9258d84f83ead24fdb0cdf9aec10838b0262f1dfbdf79c530c537","src/tests.rs":"f0e6dc1ad9223c0336c02e215ea3940acb2af6c3bc8fd791e16cd4e786e6a608","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f"},"package":"d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"}
|
||||
7
clamav/libclamav_rust/.cargo/vendor/autocfg/Cargo.lock
generated
vendored
Normal file
7
clamav/libclamav_rust/.cargo/vendor/autocfg/Cargo.lock
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
24
clamav/libclamav_rust/.cargo/vendor/autocfg/Cargo.toml
vendored
Normal file
24
clamav/libclamav_rust/.cargo/vendor/autocfg/Cargo.toml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# 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 = "autocfg"
|
||||
version = "1.1.0"
|
||||
authors = ["Josh Stone <cuviper@gmail.com>"]
|
||||
exclude = ["/.github/**", "/bors.toml"]
|
||||
description = "Automatic cfg for Rust compiler features"
|
||||
readme = "README.md"
|
||||
keywords = ["rustc", "build", "autoconf"]
|
||||
categories = ["development-tools::build-utils"]
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/cuviper/autocfg"
|
||||
|
||||
[dependencies]
|
||||
201
clamav/libclamav_rust/.cargo/vendor/autocfg/LICENSE-APACHE
vendored
Normal file
201
clamav/libclamav_rust/.cargo/vendor/autocfg/LICENSE-APACHE
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
clamav/libclamav_rust/.cargo/vendor/autocfg/LICENSE-MIT
vendored
Normal file
25
clamav/libclamav_rust/.cargo/vendor/autocfg/LICENSE-MIT
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2018 Josh Stone
|
||||
|
||||
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.
|
||||
95
clamav/libclamav_rust/.cargo/vendor/autocfg/README.md
vendored
Normal file
95
clamav/libclamav_rust/.cargo/vendor/autocfg/README.md
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
autocfg
|
||||
=======
|
||||
|
||||
[](https://crates.io/crates/autocfg)
|
||||
[](https://docs.rs/autocfg)
|
||||

|
||||

|
||||
|
||||
A Rust library for build scripts to automatically configure code based on
|
||||
compiler support. Code snippets are dynamically tested to see if the `rustc`
|
||||
will accept them, rather than hard-coding specific version support.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[build-dependencies]
|
||||
autocfg = "1"
|
||||
```
|
||||
|
||||
Then use it in your `build.rs` script to detect compiler features. For
|
||||
example, to test for 128-bit integer support, it might look like:
|
||||
|
||||
```rust
|
||||
extern crate autocfg;
|
||||
|
||||
fn main() {
|
||||
let ac = autocfg::new();
|
||||
ac.emit_has_type("i128");
|
||||
|
||||
// (optional) We don't need to rerun for anything external.
|
||||
autocfg::rerun_path("build.rs");
|
||||
}
|
||||
```
|
||||
|
||||
If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
|
||||
for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the
|
||||
rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
|
||||
should only be used when the compiler supports it.
|
||||
|
||||
|
||||
## Release Notes
|
||||
|
||||
- 1.1.0 (2022-02-07)
|
||||
- Use `CARGO_ENCODED_RUSTFLAGS` when it is set.
|
||||
|
||||
- 1.0.1 (2020-08-20)
|
||||
- Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold.
|
||||
|
||||
- 1.0.0 (2020-01-08)
|
||||
- 🎉 Release 1.0! 🎉 (no breaking changes)
|
||||
- Add `probe_expression` and `emit_expression_cfg` to test arbitrary expressions.
|
||||
- Add `probe_constant` and `emit_constant_cfg` to test arbitrary constant expressions.
|
||||
|
||||
- 0.1.7 (2019-10-20)
|
||||
- Apply `RUSTFLAGS` when probing `$TARGET != $HOST`, mainly for sysroot, by @roblabla.
|
||||
|
||||
- 0.1.6 (2019-08-19)
|
||||
- Add `probe`/`emit_sysroot_crate`, by @leo60228.
|
||||
|
||||
- 0.1.5 (2019-07-16)
|
||||
- Mask some warnings from newer rustc.
|
||||
|
||||
- 0.1.4 (2019-05-22)
|
||||
- Relax `std`/`no_std` probing to a warning instead of an error.
|
||||
- Improve `rustc` bootstrap compatibility.
|
||||
|
||||
- 0.1.3 (2019-05-21)
|
||||
- Auto-detects if `#![no_std]` is needed for the `$TARGET`.
|
||||
|
||||
- 0.1.2 (2019-01-16)
|
||||
- Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`.
|
||||
- Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`.
|
||||
|
||||
|
||||
## Minimum Rust version policy
|
||||
|
||||
This crate's minimum supported `rustc` version is `1.0.0`. Compatibility is
|
||||
its entire reason for existence, so this crate will be extremely conservative
|
||||
about raising this requirement. If this is ever deemed necessary, it will be
|
||||
treated as a major breaking change for semver purposes.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
9
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/integers.rs
vendored
Normal file
9
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/integers.rs
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
extern crate autocfg;
|
||||
|
||||
fn main() {
|
||||
// Normally, cargo will set `OUT_DIR` for build scripts.
|
||||
let ac = autocfg::AutoCfg::with_dir("target").unwrap();
|
||||
for i in 3..8 {
|
||||
ac.emit_has_type(&format!("i{}", 1 << i));
|
||||
}
|
||||
}
|
||||
22
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/paths.rs
vendored
Normal file
22
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/paths.rs
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
extern crate autocfg;
|
||||
|
||||
fn main() {
|
||||
// Normally, cargo will set `OUT_DIR` for build scripts.
|
||||
let ac = autocfg::AutoCfg::with_dir("target").unwrap();
|
||||
|
||||
// since ancient times...
|
||||
ac.emit_has_path("std::vec::Vec");
|
||||
ac.emit_path_cfg("std::vec::Vec", "has_vec");
|
||||
|
||||
// rustc 1.10.0
|
||||
ac.emit_has_path("std::panic::PanicInfo");
|
||||
ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");
|
||||
|
||||
// rustc 1.20.0
|
||||
ac.emit_has_path("std::mem::ManuallyDrop");
|
||||
ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");
|
||||
|
||||
// rustc 1.25.0
|
||||
ac.emit_has_path("std::ptr::NonNull");
|
||||
ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
|
||||
}
|
||||
26
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/traits.rs
vendored
Normal file
26
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/traits.rs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
extern crate autocfg;
|
||||
|
||||
fn main() {
|
||||
// Normally, cargo will set `OUT_DIR` for build scripts.
|
||||
let ac = autocfg::AutoCfg::with_dir("target").unwrap();
|
||||
|
||||
// since ancient times...
|
||||
ac.emit_has_trait("std::ops::Add");
|
||||
ac.emit_trait_cfg("std::ops::Add", "has_ops");
|
||||
|
||||
// trait parameters have to be provided
|
||||
ac.emit_has_trait("std::borrow::Borrow<str>");
|
||||
ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");
|
||||
|
||||
// rustc 1.8.0
|
||||
ac.emit_has_trait("std::ops::AddAssign");
|
||||
ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");
|
||||
|
||||
// rustc 1.12.0
|
||||
ac.emit_has_trait("std::iter::Sum");
|
||||
ac.emit_trait_cfg("std::iter::Sum", "has_sum");
|
||||
|
||||
// rustc 1.28.0
|
||||
ac.emit_has_trait("std::alloc::GlobalAlloc");
|
||||
ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
|
||||
}
|
||||
9
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/versions.rs
vendored
Normal file
9
clamav/libclamav_rust/.cargo/vendor/autocfg/examples/versions.rs
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
extern crate autocfg;
|
||||
|
||||
fn main() {
|
||||
// Normally, cargo will set `OUT_DIR` for build scripts.
|
||||
let ac = autocfg::AutoCfg::with_dir("target").unwrap();
|
||||
for i in 0..100 {
|
||||
ac.emit_rustc_version(1, i);
|
||||
}
|
||||
}
|
||||
69
clamav/libclamav_rust/.cargo/vendor/autocfg/src/error.rs
vendored
Normal file
69
clamav/libclamav_rust/.cargo/vendor/autocfg/src/error.rs
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::num;
|
||||
use std::str;
|
||||
|
||||
/// A common error type for the `autocfg` crate.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
kind: ErrorKind,
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
"AutoCfg error"
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
match self.kind {
|
||||
ErrorKind::Io(ref e) => Some(e),
|
||||
ErrorKind::Num(ref e) => Some(e),
|
||||
ErrorKind::Utf8(ref e) => Some(e),
|
||||
ErrorKind::Other(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match self.kind {
|
||||
ErrorKind::Io(ref e) => e.fmt(f),
|
||||
ErrorKind::Num(ref e) => e.fmt(f),
|
||||
ErrorKind::Utf8(ref e) => e.fmt(f),
|
||||
ErrorKind::Other(s) => s.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ErrorKind {
|
||||
Io(io::Error),
|
||||
Num(num::ParseIntError),
|
||||
Utf8(str::Utf8Error),
|
||||
Other(&'static str),
|
||||
}
|
||||
|
||||
pub fn from_io(e: io::Error) -> Error {
|
||||
Error {
|
||||
kind: ErrorKind::Io(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_num(e: num::ParseIntError) -> Error {
|
||||
Error {
|
||||
kind: ErrorKind::Num(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_utf8(e: str::Utf8Error) -> Error {
|
||||
Error {
|
||||
kind: ErrorKind::Utf8(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(s: &'static str) -> Error {
|
||||
Error {
|
||||
kind: ErrorKind::Other(s),
|
||||
}
|
||||
}
|
||||
453
clamav/libclamav_rust/.cargo/vendor/autocfg/src/lib.rs
vendored
Normal file
453
clamav/libclamav_rust/.cargo/vendor/autocfg/src/lib.rs
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
//! A Rust library for build scripts to automatically configure code based on
|
||||
//! compiler support. Code snippets are dynamically tested to see if the `rustc`
|
||||
//! will accept them, rather than hard-coding specific version support.
|
||||
//!
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! Add this to your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [build-dependencies]
|
||||
//! autocfg = "1"
|
||||
//! ```
|
||||
//!
|
||||
//! Then use it in your `build.rs` script to detect compiler features. For
|
||||
//! example, to test for 128-bit integer support, it might look like:
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate autocfg;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! # // Normally, cargo will set `OUT_DIR` for build scripts.
|
||||
//! # std::env::set_var("OUT_DIR", "target");
|
||||
//! let ac = autocfg::new();
|
||||
//! ac.emit_has_type("i128");
|
||||
//!
|
||||
//! // (optional) We don't need to rerun for anything external.
|
||||
//! autocfg::rerun_path("build.rs");
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
|
||||
//! for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the
|
||||
//! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
|
||||
//! should only be used when the compiler supports it.
|
||||
//!
|
||||
//! ## Caution
|
||||
//!
|
||||
//! Many of the probing methods of `AutoCfg` document the particular template they
|
||||
//! use, **subject to change**. The inputs are not validated to make sure they are
|
||||
//! semantically correct for their expected use, so it's _possible_ to escape and
|
||||
//! inject something unintended. However, such abuse is unsupported and will not
|
||||
//! be considered when making changes to the templates.
|
||||
|
||||
#![deny(missing_debug_implementations)]
|
||||
#![deny(missing_docs)]
|
||||
// allow future warnings that can't be fixed while keeping 1.0 compatibility
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(bare_trait_objects)]
|
||||
#![allow(ellipsis_inclusive_range_patterns)]
|
||||
|
||||
/// Local macro to avoid `std::try!`, deprecated in Rust 1.39.
|
||||
macro_rules! try {
|
||||
($result:expr) => {
|
||||
match $result {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::io::{stderr, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
#[allow(deprecated)]
|
||||
use std::sync::atomic::ATOMIC_USIZE_INIT;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
mod error;
|
||||
pub use error::Error;
|
||||
|
||||
mod version;
|
||||
use version::Version;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Helper to detect compiler features for `cfg` output in build scripts.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AutoCfg {
|
||||
out_dir: PathBuf,
|
||||
rustc: PathBuf,
|
||||
rustc_version: Version,
|
||||
target: Option<OsString>,
|
||||
no_std: bool,
|
||||
rustflags: Vec<String>,
|
||||
}
|
||||
|
||||
/// Writes a config flag for rustc on standard out.
|
||||
///
|
||||
/// This looks like: `cargo:rustc-cfg=CFG`
|
||||
///
|
||||
/// Cargo will use this in arguments to rustc, like `--cfg CFG`.
|
||||
pub fn emit(cfg: &str) {
|
||||
println!("cargo:rustc-cfg={}", cfg);
|
||||
}
|
||||
|
||||
/// Writes a line telling Cargo to rerun the build script if `path` changes.
|
||||
///
|
||||
/// This looks like: `cargo:rerun-if-changed=PATH`
|
||||
///
|
||||
/// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0. Earlier
|
||||
/// versions of cargo will simply ignore the directive.
|
||||
pub fn rerun_path(path: &str) {
|
||||
println!("cargo:rerun-if-changed={}", path);
|
||||
}
|
||||
|
||||
/// Writes a line telling Cargo to rerun the build script if the environment
|
||||
/// variable `var` changes.
|
||||
///
|
||||
/// This looks like: `cargo:rerun-if-env-changed=VAR`
|
||||
///
|
||||
/// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0. Earlier
|
||||
/// versions of cargo will simply ignore the directive.
|
||||
pub fn rerun_env(var: &str) {
|
||||
println!("cargo:rerun-if-env-changed={}", var);
|
||||
}
|
||||
|
||||
/// Create a new `AutoCfg` instance.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `AutoCfg::new()` returns an error.
|
||||
pub fn new() -> AutoCfg {
|
||||
AutoCfg::new().unwrap()
|
||||
}
|
||||
|
||||
impl AutoCfg {
|
||||
/// Create a new `AutoCfg` instance.
|
||||
///
|
||||
/// # Common errors
|
||||
///
|
||||
/// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
|
||||
/// - The version output from `rustc` can't be parsed.
|
||||
/// - `OUT_DIR` is not set in the environment, or is not a writable directory.
|
||||
///
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
match env::var_os("OUT_DIR") {
|
||||
Some(d) => Self::with_dir(d),
|
||||
None => Err(error::from_str("no OUT_DIR specified!")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new `AutoCfg` instance with the specified output directory.
|
||||
///
|
||||
/// # Common errors
|
||||
///
|
||||
/// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
|
||||
/// - The version output from `rustc` can't be parsed.
|
||||
/// - `dir` is not a writable directory.
|
||||
///
|
||||
pub fn with_dir<T: Into<PathBuf>>(dir: T) -> Result<Self, Error> {
|
||||
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
|
||||
let rustc: PathBuf = rustc.into();
|
||||
let rustc_version = try!(Version::from_rustc(&rustc));
|
||||
|
||||
let target = env::var_os("TARGET");
|
||||
|
||||
// Sanity check the output directory
|
||||
let dir = dir.into();
|
||||
let meta = try!(fs::metadata(&dir).map_err(error::from_io));
|
||||
if !meta.is_dir() || meta.permissions().readonly() {
|
||||
return Err(error::from_str("output path is not a writable directory"));
|
||||
}
|
||||
|
||||
let mut ac = AutoCfg {
|
||||
rustflags: rustflags(&target, &dir),
|
||||
out_dir: dir,
|
||||
rustc: rustc,
|
||||
rustc_version: rustc_version,
|
||||
target: target,
|
||||
no_std: false,
|
||||
};
|
||||
|
||||
// Sanity check with and without `std`.
|
||||
if !ac.probe("").unwrap_or(false) {
|
||||
ac.no_std = true;
|
||||
if !ac.probe("").unwrap_or(false) {
|
||||
// Neither worked, so assume nothing...
|
||||
ac.no_std = false;
|
||||
let warning = b"warning: autocfg could not probe for `std`\n";
|
||||
stderr().write_all(warning).ok();
|
||||
}
|
||||
}
|
||||
Ok(ac)
|
||||
}
|
||||
|
||||
/// Test whether the current `rustc` reports a version greater than
|
||||
/// or equal to "`major`.`minor`".
|
||||
pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool {
|
||||
self.rustc_version >= Version::new(major, minor, 0)
|
||||
}
|
||||
|
||||
/// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`,
|
||||
/// if the current `rustc` is at least that version.
|
||||
pub fn emit_rustc_version(&self, major: usize, minor: usize) {
|
||||
if self.probe_rustc_version(major, minor) {
|
||||
emit(&format!("rustc_{}_{}", major, minor));
|
||||
}
|
||||
}
|
||||
|
||||
fn probe<T: AsRef<[u8]>>(&self, code: T) -> Result<bool, Error> {
|
||||
#[allow(deprecated)]
|
||||
static ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
let id = ID.fetch_add(1, Ordering::Relaxed);
|
||||
let mut command = Command::new(&self.rustc);
|
||||
command
|
||||
.arg("--crate-name")
|
||||
.arg(format!("probe{}", id))
|
||||
.arg("--crate-type=lib")
|
||||
.arg("--out-dir")
|
||||
.arg(&self.out_dir)
|
||||
.arg("--emit=llvm-ir");
|
||||
|
||||
if let Some(target) = self.target.as_ref() {
|
||||
command.arg("--target").arg(target);
|
||||
}
|
||||
|
||||
command.args(&self.rustflags);
|
||||
|
||||
command.arg("-").stdin(Stdio::piped());
|
||||
let mut child = try!(command.spawn().map_err(error::from_io));
|
||||
let mut stdin = child.stdin.take().expect("rustc stdin");
|
||||
|
||||
if self.no_std {
|
||||
try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io));
|
||||
}
|
||||
try!(stdin.write_all(code.as_ref()).map_err(error::from_io));
|
||||
drop(stdin);
|
||||
|
||||
let status = try!(child.wait().map_err(error::from_io));
|
||||
Ok(status.success())
|
||||
}
|
||||
|
||||
/// Tests whether the given sysroot crate can be used.
|
||||
///
|
||||
/// The test code is subject to change, but currently looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// extern crate CRATE as probe;
|
||||
/// ```
|
||||
pub fn probe_sysroot_crate(&self, name: &str) -> bool {
|
||||
self.probe(format!("extern crate {} as probe;", name)) // `as _` wasn't stabilized until Rust 1.33
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true.
|
||||
pub fn emit_sysroot_crate(&self, name: &str) {
|
||||
if self.probe_sysroot_crate(name) {
|
||||
emit(&format!("has_{}", mangle(name)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether the given path can be used.
|
||||
///
|
||||
/// The test code is subject to change, but currently looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub use PATH;
|
||||
/// ```
|
||||
pub fn probe_path(&self, path: &str) -> bool {
|
||||
self.probe(format!("pub use {};", path)).unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Emits a config value `has_PATH` if `probe_path` returns true.
|
||||
///
|
||||
/// Any non-identifier characters in the `path` will be replaced with
|
||||
/// `_` in the generated config value.
|
||||
pub fn emit_has_path(&self, path: &str) {
|
||||
if self.probe_path(path) {
|
||||
emit(&format!("has_{}", mangle(path)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits the given `cfg` value if `probe_path` returns true.
|
||||
pub fn emit_path_cfg(&self, path: &str, cfg: &str) {
|
||||
if self.probe_path(path) {
|
||||
emit(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether the given trait can be used.
|
||||
///
|
||||
/// The test code is subject to change, but currently looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub trait Probe: TRAIT + Sized {}
|
||||
/// ```
|
||||
pub fn probe_trait(&self, name: &str) -> bool {
|
||||
self.probe(format!("pub trait Probe: {} + Sized {{}}", name))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Emits a config value `has_TRAIT` if `probe_trait` returns true.
|
||||
///
|
||||
/// Any non-identifier characters in the trait `name` will be replaced with
|
||||
/// `_` in the generated config value.
|
||||
pub fn emit_has_trait(&self, name: &str) {
|
||||
if self.probe_trait(name) {
|
||||
emit(&format!("has_{}", mangle(name)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits the given `cfg` value if `probe_trait` returns true.
|
||||
pub fn emit_trait_cfg(&self, name: &str, cfg: &str) {
|
||||
if self.probe_trait(name) {
|
||||
emit(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether the given type can be used.
|
||||
///
|
||||
/// The test code is subject to change, but currently looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub type Probe = TYPE;
|
||||
/// ```
|
||||
pub fn probe_type(&self, name: &str) -> bool {
|
||||
self.probe(format!("pub type Probe = {};", name))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Emits a config value `has_TYPE` if `probe_type` returns true.
|
||||
///
|
||||
/// Any non-identifier characters in the type `name` will be replaced with
|
||||
/// `_` in the generated config value.
|
||||
pub fn emit_has_type(&self, name: &str) {
|
||||
if self.probe_type(name) {
|
||||
emit(&format!("has_{}", mangle(name)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits the given `cfg` value if `probe_type` returns true.
|
||||
pub fn emit_type_cfg(&self, name: &str, cfg: &str) {
|
||||
if self.probe_type(name) {
|
||||
emit(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether the given expression can be used.
|
||||
///
|
||||
/// The test code is subject to change, but currently looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub fn probe() { let _ = EXPR; }
|
||||
/// ```
|
||||
pub fn probe_expression(&self, expr: &str) -> bool {
|
||||
self.probe(format!("pub fn probe() {{ let _ = {}; }}", expr))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Emits the given `cfg` value if `probe_expression` returns true.
|
||||
pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) {
|
||||
if self.probe_expression(expr) {
|
||||
emit(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether the given constant expression can be used.
|
||||
///
|
||||
/// The test code is subject to change, but currently looks like:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub const PROBE: () = ((), EXPR).0;
|
||||
/// ```
|
||||
pub fn probe_constant(&self, expr: &str) -> bool {
|
||||
self.probe(format!("pub const PROBE: () = ((), {}).0;", expr))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Emits the given `cfg` value if `probe_constant` returns true.
|
||||
pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) {
|
||||
if self.probe_constant(expr) {
|
||||
emit(cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mangle(s: &str) -> String {
|
||||
s.chars()
|
||||
.map(|c| match c {
|
||||
'A'...'Z' | 'a'...'z' | '0'...'9' => c,
|
||||
_ => '_',
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn dir_contains_target(
|
||||
target: &Option<OsString>,
|
||||
dir: &Path,
|
||||
cargo_target_dir: Option<OsString>,
|
||||
) -> bool {
|
||||
target
|
||||
.as_ref()
|
||||
.and_then(|target| {
|
||||
dir.to_str().and_then(|dir| {
|
||||
let mut cargo_target_dir = cargo_target_dir
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| PathBuf::from("target"));
|
||||
cargo_target_dir.push(target);
|
||||
|
||||
cargo_target_dir
|
||||
.to_str()
|
||||
.map(|cargo_target_dir| dir.contains(&cargo_target_dir))
|
||||
})
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn rustflags(target: &Option<OsString>, dir: &Path) -> Vec<String> {
|
||||
// Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets
|
||||
// CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This
|
||||
// includes any source of flags, whether from the environment, toml config, or
|
||||
// whatever may come in the future. The value is either an empty string, or a
|
||||
// list of arguments separated by the ASCII unit separator (US), 0x1f.
|
||||
if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") {
|
||||
return if a.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
a.split('\x1f').map(str::to_string).collect()
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise, we have to take a more heuristic approach, and we don't
|
||||
// support values from toml config at all.
|
||||
//
|
||||
// Cargo only applies RUSTFLAGS for building TARGET artifact in
|
||||
// cross-compilation environment. Sadly, we don't have a way to detect
|
||||
// when we're building HOST artifact in a cross-compilation environment,
|
||||
// so for now we only apply RUSTFLAGS when cross-compiling an artifact.
|
||||
//
|
||||
// See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030.
|
||||
if *target != env::var_os("HOST")
|
||||
|| dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR"))
|
||||
{
|
||||
if let Ok(rustflags) = env::var("RUSTFLAGS") {
|
||||
// This is meant to match how cargo handles the RUSTFLAGS environment variable.
|
||||
// See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441
|
||||
return rustflags
|
||||
.split(' ')
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(str::to_string)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
Vec::new()
|
||||
}
|
||||
174
clamav/libclamav_rust/.cargo/vendor/autocfg/src/tests.rs
vendored
Normal file
174
clamav/libclamav_rust/.cargo/vendor/autocfg/src/tests.rs
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
use super::AutoCfg;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
impl AutoCfg {
|
||||
fn core_std(&self, path: &str) -> String {
|
||||
let krate = if self.no_std { "core" } else { "std" };
|
||||
format!("{}::{}", krate, path)
|
||||
}
|
||||
|
||||
fn assert_std(&self, probe_result: bool) {
|
||||
assert_eq!(!self.no_std, probe_result);
|
||||
}
|
||||
|
||||
fn assert_min(&self, major: usize, minor: usize, probe_result: bool) {
|
||||
assert_eq!(self.probe_rustc_version(major, minor), probe_result);
|
||||
}
|
||||
|
||||
fn for_test() -> Result<Self, super::error::Error> {
|
||||
match env::var_os("TESTS_TARGET_DIR") {
|
||||
Some(d) => Self::with_dir(d),
|
||||
None => Self::with_dir("target"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autocfg_version() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
println!("version: {:?}", ac.rustc_version);
|
||||
assert!(ac.probe_rustc_version(1, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_cmp() {
|
||||
use super::version::Version;
|
||||
let v123 = Version::new(1, 2, 3);
|
||||
|
||||
assert!(Version::new(1, 0, 0) < v123);
|
||||
assert!(Version::new(1, 2, 2) < v123);
|
||||
assert!(Version::new(1, 2, 3) == v123);
|
||||
assert!(Version::new(1, 2, 4) > v123);
|
||||
assert!(Version::new(1, 10, 0) > v123);
|
||||
assert!(Version::new(2, 0, 0) > v123);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_add() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
let add = ac.core_std("ops::Add");
|
||||
let add_rhs = add.clone() + "<i32>";
|
||||
let add_rhs_output = add.clone() + "<i32, Output = i32>";
|
||||
let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output;
|
||||
assert!(ac.probe_path(&add));
|
||||
assert!(ac.probe_trait(&add));
|
||||
assert!(ac.probe_trait(&add_rhs));
|
||||
assert!(ac.probe_trait(&add_rhs_output));
|
||||
ac.assert_min(1, 27, ac.probe_type(&dyn_add_rhs_output));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_as_ref() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
let as_ref = ac.core_std("convert::AsRef");
|
||||
let as_ref_str = as_ref.clone() + "<str>";
|
||||
let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str;
|
||||
assert!(ac.probe_path(&as_ref));
|
||||
assert!(ac.probe_trait(&as_ref_str));
|
||||
assert!(ac.probe_type(&as_ref_str));
|
||||
ac.assert_min(1, 27, ac.probe_type(&dyn_as_ref_str));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_i128() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
let i128_path = ac.core_std("i128");
|
||||
ac.assert_min(1, 26, ac.probe_path(&i128_path));
|
||||
ac.assert_min(1, 26, ac.probe_type("i128"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_sum() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
let sum = ac.core_std("iter::Sum");
|
||||
let sum_i32 = sum.clone() + "<i32>";
|
||||
let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32;
|
||||
ac.assert_min(1, 12, ac.probe_path(&sum));
|
||||
ac.assert_min(1, 12, ac.probe_trait(&sum));
|
||||
ac.assert_min(1, 12, ac.probe_trait(&sum_i32));
|
||||
ac.assert_min(1, 12, ac.probe_type(&sum_i32));
|
||||
ac.assert_min(1, 27, ac.probe_type(&dyn_sum_i32));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_std() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
ac.assert_std(ac.probe_sysroot_crate("std"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_alloc() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
ac.assert_min(1, 36, ac.probe_sysroot_crate("alloc"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_bad_sysroot_crate() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
assert!(!ac.probe_sysroot_crate("doesnt_exist"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_no_std() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
assert!(ac.probe_type("i32"));
|
||||
assert!(ac.probe_type("[i32]"));
|
||||
ac.assert_std(ac.probe_type("Vec<i32>"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_expression() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
assert!(ac.probe_expression(r#""test".trim_left()"#));
|
||||
ac.assert_min(1, 30, ac.probe_expression(r#""test".trim_start()"#));
|
||||
ac.assert_std(ac.probe_expression("[1, 2, 3].to_vec()"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probe_constant() {
|
||||
let ac = AutoCfg::for_test().unwrap();
|
||||
assert!(ac.probe_constant("1 + 2 + 3"));
|
||||
ac.assert_min(1, 33, ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"));
|
||||
ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_does_not_contain_target() {
|
||||
assert!(!super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new("/project/target/debug/build/project-ea75983148559682/out"),
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_does_contain_target() {
|
||||
assert!(super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new(
|
||||
"/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
|
||||
),
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_does_not_contain_target_with_custom_target_dir() {
|
||||
assert!(!super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new("/project/custom/debug/build/project-ea75983148559682/out"),
|
||||
Some("custom".into()),
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_does_contain_target_with_custom_target_dir() {
|
||||
assert!(super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new(
|
||||
"/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
|
||||
),
|
||||
Some("custom".into()),
|
||||
));
|
||||
}
|
||||
60
clamav/libclamav_rust/.cargo/vendor/autocfg/src/version.rs
vendored
Normal file
60
clamav/libclamav_rust/.cargo/vendor/autocfg/src/version.rs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
|
||||
use super::{error, Error};
|
||||
|
||||
/// A version structure for making relative comparisons.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Version {
|
||||
major: usize,
|
||||
minor: usize,
|
||||
patch: usize,
|
||||
}
|
||||
|
||||
impl Version {
|
||||
/// Creates a `Version` instance for a specific `major.minor.patch` version.
|
||||
pub fn new(major: usize, minor: usize, patch: usize) -> Self {
|
||||
Version {
|
||||
major: major,
|
||||
minor: minor,
|
||||
patch: patch,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rustc(rustc: &Path) -> Result<Self, Error> {
|
||||
// Get rustc's verbose version
|
||||
let output = try!(Command::new(rustc)
|
||||
.args(&["--version", "--verbose"])
|
||||
.output()
|
||||
.map_err(error::from_io));
|
||||
if !output.status.success() {
|
||||
return Err(error::from_str("could not execute rustc"));
|
||||
}
|
||||
let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8));
|
||||
|
||||
// Find the release line in the verbose version output.
|
||||
let release = match output.lines().find(|line| line.starts_with("release: ")) {
|
||||
Some(line) => &line["release: ".len()..],
|
||||
None => return Err(error::from_str("could not find rustc release")),
|
||||
};
|
||||
|
||||
// Strip off any extra channel info, e.g. "-beta.N", "-nightly"
|
||||
let version = match release.find('-') {
|
||||
Some(i) => &release[..i],
|
||||
None => release,
|
||||
};
|
||||
|
||||
// Split the version into semver components.
|
||||
let mut iter = version.splitn(3, '.');
|
||||
let major = try!(iter.next().ok_or(error::from_str("missing major version")));
|
||||
let minor = try!(iter.next().ok_or(error::from_str("missing minor version")));
|
||||
let patch = try!(iter.next().ok_or(error::from_str("missing patch version")));
|
||||
|
||||
Ok(Version::new(
|
||||
try!(major.parse().map_err(error::from_num)),
|
||||
try!(minor.parse().map_err(error::from_num)),
|
||||
try!(patch.parse().map_err(error::from_num)),
|
||||
))
|
||||
}
|
||||
}
|
||||
33
clamav/libclamav_rust/.cargo/vendor/autocfg/tests/rustflags.rs
vendored
Normal file
33
clamav/libclamav_rust/.cargo/vendor/autocfg/tests/rustflags.rs
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
extern crate autocfg;
|
||||
|
||||
use std::env;
|
||||
|
||||
/// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS
|
||||
/// environment variables when running rustc.
|
||||
#[test]
|
||||
fn test_with_sysroot() {
|
||||
// Use the same path as this test binary.
|
||||
let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
|
||||
env::set_var("OUT_DIR", &format!("{}", dir.display()));
|
||||
|
||||
// If we have encoded rustflags, they take precedence, even if empty.
|
||||
env::set_var("CARGO_ENCODED_RUSTFLAGS", "");
|
||||
env::set_var("RUSTFLAGS", &format!("-L {}", dir.display()));
|
||||
let ac = autocfg::AutoCfg::new().unwrap();
|
||||
assert!(ac.probe_sysroot_crate("std"));
|
||||
assert!(!ac.probe_sysroot_crate("autocfg"));
|
||||
|
||||
// Now try again with useful encoded args.
|
||||
env::set_var(
|
||||
"CARGO_ENCODED_RUSTFLAGS",
|
||||
&format!("-L\x1f{}", dir.display()),
|
||||
);
|
||||
let ac = autocfg::AutoCfg::new().unwrap();
|
||||
assert!(ac.probe_sysroot_crate("autocfg"));
|
||||
|
||||
// Try the old-style RUSTFLAGS, ensuring HOST != TARGET.
|
||||
env::remove_var("CARGO_ENCODED_RUSTFLAGS");
|
||||
env::set_var("HOST", "lol");
|
||||
let ac = autocfg::AutoCfg::new().unwrap();
|
||||
assert!(ac.probe_sysroot_crate("autocfg"));
|
||||
}
|
||||
1
clamav/libclamav_rust/.cargo/vendor/bindgen/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/bindgen/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"Cargo.lock":"a915231b52b67320c7d440eb711c99632e4b948e5dcbeb6835e18bd0d798c76a","Cargo.toml":"655f82f7efb9e6b434a4710d8b1ea5b8c2116bccc6d8a4f87a7abc9e0c69051b","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"c093205492ab9f00f275c50aacfc9058264d3dcc7c7d2ff83e0cc4858d1cee49","build.rs":"d53484feea4cd147cd80280ac270c24ab727386acabb043e6347c44ac5369d0e","csmith-fuzzing/README.md":"7107b70fedb0c0a0cadb3c439a49c1bd0119a6d38dc63b1aecc74d1942256ef2","src/callbacks.rs":"cb4ca440e356dde75919a5298b75cbf145c981c2e1da62907337706286dd5c9e","src/clang.rs":"6b02ae174012372d00b442b5ec5a66a6122a091217039e5ba4917578c769d01f","src/codegen/bitfield_unit.rs":"fddeaeab5859f4e82081865595b7705f5c0774d997df95fa5c655b81b9cae125","src/codegen/bitfield_unit_tests.rs":"9df86490de5e9d66ccea583dcb686dd440375dc1a3c3cf89a89d5de3883bf28a","src/codegen/dyngen.rs":"b1bca96fbd81b1c0678122df8d28f3b60cd74047a43d0d298d69feb06eecf459","src/codegen/error.rs":"5e308b8c54b68511fc8ea2ad15ddac510172c4ff460a80a265336440b0c9653d","src/codegen/helpers.rs":"b4e2ee991e83fda62b0aebd562b948eba785179cb4aa1a154d00ffad215b7be5","src/codegen/impl_debug.rs":"71d8e28873ba2de466f2637a824746963702f0511728037d72ee5670c51194cb","src/codegen/impl_partialeq.rs":"f4599e32c66179ae515a6518a3e94b686689cf59f7dd9ab618c3fb69f17d2c77","src/codegen/mod.rs":"a286fa9a31254ce317c4baad05af446b59aaa23fb80aba9f260e67d15c64ff8c","src/codegen/struct_layout.rs":"d03e66412f4bb1fa59c623873b2a22e100d029a002c07aaf4586f4852a410b54","src/deps.rs":"de4a91d1d252295e1abaf4ab1f90f7be618c67649edb12081c3a501e61398a75","src/extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","src/features.rs":"f93bb757400580a75adc6a187cdeb032ec4d6efe7d3fcb9a6864472edd875580","src/ir/analysis/derive.rs":"066d35cdb7523c5edd141394286911128261b4db23cc17520e3b3111ef1bb51e","src/ir/analysis/has_destructor.rs":"7a82f01e7e0595a31b56f7c398fa3019b3fe9100a2a73b56768f7e6943dcc3ce","src/ir/analysis/has_float.rs":"58ea1e38a59ef208400fd65d426cb5b288949df2d383b3a194fa01b99d2a87fa","src/ir/analysis/has_type_param_in_array.rs":"d1b9eb119dc14f662eb9bd1394c859f485479e4912589709cdd33f6752094e22","src/ir/analysis/has_vtable.rs":"368cf30fbe3fab7190fab48718b948caac5da8c9e797b709488716b919315636","src/ir/analysis/mod.rs":"cde4ce0667d1895008c9b2af479211c828740fcb59fa13d600cbdc100fa8bdc5","src/ir/analysis/sizedness.rs":"944443d6aab35d2dd80e4f5e59176ac1e1c463ba2f0eb25d33f1d95dfac1a6d0","src/ir/analysis/template_params.rs":"a2d2e247c2f51cd90e83f11bce0305c2e498232d015f88192b44e8522e7fd8b1","src/ir/annotations.rs":"456276ef7f9b04e40b7b10aa7570d98b11aae8efe676679881459ae878bbecfc","src/ir/comment.rs":"9c0c4789c0893b636fac42228f8a0292a06cb4f2b7431895490784dd16b7f79a","src/ir/comp.rs":"811a2abfbf8ed6925327ad005a460ca698d40a2d5d4698015e1bcd4e7d2c9cf0","src/ir/context.rs":"df486590515ffaab8b51c96699a239de202569a8718d9c4b79a8ccc8808cee69","src/ir/derive.rs":"e5581852eec87918901a129284b4965aefc8a19394187a8095779a084f28fabe","src/ir/dot.rs":"2d79d698e6ac59ce032840e62ff11103abed1d5e9e700cf383b492333eeebe1f","src/ir/enum_ty.rs":"c2d928bb1a8453922c962cb11a7ab3b737c5651599141ece8d31e21e6eb74585","src/ir/function.rs":"3e13078b36ee02142017cfbbaaeb9e64ef485a12e151096e12f54a8fde984505","src/ir/int.rs":"68a86182743ec338d58e42203364dc7c8970cb7ec3550433ca92f0c9489b4442","src/ir/item.rs":"1c79d6dd400ab01545a19214847245b440690bfe129895f164bef460ee41b857","src/ir/item_kind.rs":"7666a1ff1b8260978b790a08b4139ab56b5c65714a5652bbcec7faa7443adc36","src/ir/layout.rs":"d6bd9a14b94320f9e2517bf9fc9ffaf4220954fa24d77d90bba070dbede7392b","src/ir/mod.rs":"713cd537434567003197a123cbae679602c715e976d22f7b23dafd0826ea4c70","src/ir/module.rs":"7cae5561bcf84a5c3b1ee8f1c3336a33b7f44f0d5ffe885fb108289983fe763e","src/ir/objc.rs":"dd394c1db6546cbe5111ce5cd2f211f9839aba81c5e7228c2a68fba386bc259f","src/ir/template.rs":"3bb3e7f6ec28eff73c2032922d30b93d70da117b848e9cb02bdf6c9a74294f7f","src/ir/traversal.rs":"105d93bc2f1f55033c621667a0e55153844eec34560ae88183f799d0d0c1a6f2","src/ir/ty.rs":"2ecae57f018732b6daf1c08fc98765456a9e6a24cbceaf7f1bc004676b0113ee","src/ir/var.rs":"fe7720438af43fa3bbe3850aff331bb47131b2c21e975f92bfbcdc182789105a","src/lib.rs":"0f148aef6fd6ae814df29317fe5860d0c1747c40d5182f2518d3b81a03b6587a","src/log_stubs.rs":"9f974e041e35c8c7e29985d27ae5cd0858d68f8676d1dc005c6388d7d011707f","src/main.rs":"188cd89581490eb5f26a194cc25e4f38f3e0b93eed7ad591bc73362febd26b72","src/options.rs":"14190fae2aaad331f0660e4cc1d5a1fea0c2c88696091715867a3e7282a1d7b5","src/parse.rs":"4ffc54415eadb622ee488603862788c78361ef2c889de25259441a340c2a010f","src/regex_set.rs":"6c46357fb1ee68250e5e017cbf691f340041489ae78599eee7a5665a6ddce27f","src/time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"}
|
||||
446
clamav/libclamav_rust/.cargo/vendor/bindgen/Cargo.lock
generated
vendored
Normal file
446
clamav/libclamav_rust/.cargo/vendor/bindgen/Cargo.lock
generated
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.59.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"clap",
|
||||
"diff",
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"tempfile",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "853eda514c284c2287f4bf20ae614f8781f40a81d32ecda6e91449304dfe077c"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cc009ab82a2afc94b9e467ab4214aee9cad1356cd9191264203d7d72006e00d"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
115
clamav/libclamav_rust/.cargo/vendor/bindgen/Cargo.toml
vendored
Normal file
115
clamav/libclamav_rust/.cargo/vendor/bindgen/Cargo.toml
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
# 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 = "bindgen"
|
||||
version = "0.59.2"
|
||||
authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
|
||||
build = "build.rs"
|
||||
include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
|
||||
description = "Automatically generates Rust FFI bindings to C and C++ libraries."
|
||||
homepage = "https://rust-lang.github.io/rust-bindgen/"
|
||||
documentation = "https://docs.rs/bindgen"
|
||||
readme = "README.md"
|
||||
keywords = ["bindings", "ffi", "code-generation"]
|
||||
categories = ["external-ffi-bindings", "development-tools::ffi"]
|
||||
license = "BSD-3-Clause"
|
||||
repository = "https://github.com/rust-lang/rust-bindgen"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "bindgen"
|
||||
path = "src/main.rs"
|
||||
doc = false
|
||||
required-features = ["clap"]
|
||||
[dependencies.bitflags]
|
||||
version = "1.0.3"
|
||||
|
||||
[dependencies.cexpr]
|
||||
version = "0.6"
|
||||
|
||||
[dependencies.clang-sys]
|
||||
version = "1"
|
||||
features = ["clang_6_0"]
|
||||
|
||||
[dependencies.clap]
|
||||
version = "2"
|
||||
optional = true
|
||||
|
||||
[dependencies.env_logger]
|
||||
version = "0.9.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1"
|
||||
|
||||
[dependencies.lazycell]
|
||||
version = "1"
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
optional = true
|
||||
|
||||
[dependencies.peeking_take_while]
|
||||
version = "0.1.2"
|
||||
|
||||
[dependencies.proc-macro2]
|
||||
version = "1"
|
||||
default-features = false
|
||||
|
||||
[dependencies.quote]
|
||||
version = "1"
|
||||
default-features = false
|
||||
|
||||
[dependencies.regex]
|
||||
version = "1.0"
|
||||
features = ["std", "unicode"]
|
||||
default-features = false
|
||||
|
||||
[dependencies.rustc-hash]
|
||||
version = "1.0.1"
|
||||
|
||||
[dependencies.shlex]
|
||||
version = "1"
|
||||
|
||||
[dependencies.which]
|
||||
version = "4.2.1"
|
||||
optional = true
|
||||
default-features = false
|
||||
[dev-dependencies.clap]
|
||||
version = "2"
|
||||
|
||||
[dev-dependencies.diff]
|
||||
version = "0.1"
|
||||
|
||||
[dev-dependencies.shlex]
|
||||
version = "1"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = "3"
|
||||
|
||||
[features]
|
||||
default = ["logging", "clap", "runtime", "which-rustfmt"]
|
||||
logging = ["env_logger", "log"]
|
||||
runtime = ["clang-sys/runtime"]
|
||||
static = ["clang-sys/static"]
|
||||
testing_only_docs = []
|
||||
testing_only_extra_assertions = []
|
||||
testing_only_libclang_3_9 = []
|
||||
testing_only_libclang_4 = []
|
||||
testing_only_libclang_5 = []
|
||||
testing_only_libclang_9 = []
|
||||
which-rustfmt = ["which"]
|
||||
[badges.travis-ci]
|
||||
repository = "rust-lang/rust-bindgen"
|
||||
29
clamav/libclamav_rust/.cargo/vendor/bindgen/LICENSE
vendored
Normal file
29
clamav/libclamav_rust/.cargo/vendor/bindgen/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2013, Jyun-Yan You
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
83
clamav/libclamav_rust/.cargo/vendor/bindgen/README.md
vendored
Normal file
83
clamav/libclamav_rust/.cargo/vendor/bindgen/README.md
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
[](https://crates.io/crates/bindgen)
|
||||
[](https://docs.rs/bindgen/)
|
||||
|
||||
# `bindgen`
|
||||
|
||||
**`bindgen` automatically generates Rust FFI bindings to C (and some C++) libraries.**
|
||||
|
||||
For example, given the C header `doggo.h`:
|
||||
|
||||
```c
|
||||
typedef struct Doggo {
|
||||
int many;
|
||||
char wow;
|
||||
} Doggo;
|
||||
|
||||
void eleven_out_of_ten_majestic_af(Doggo* pupper);
|
||||
```
|
||||
|
||||
`bindgen` produces Rust FFI code allowing you to call into the `doggo` library's
|
||||
functions and use its types:
|
||||
|
||||
```rust
|
||||
/* automatically generated by rust-bindgen 0.99.9 */
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Doggo {
|
||||
pub many: ::std::os::raw::c_int,
|
||||
pub wow: ::std::os::raw::c_char,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn eleven_out_of_ten_majestic_af(pupper: *mut Doggo);
|
||||
}
|
||||
```
|
||||
|
||||
## Users Guide
|
||||
|
||||
[📚 Read the `bindgen` users guide here! 📚](https://rust-lang.github.io/rust-bindgen)
|
||||
|
||||
## MSRV
|
||||
|
||||
The minimum supported Rust version is **1.46**.
|
||||
|
||||
No MSRV bump policy has been established yet, so MSRV may increase in any release.
|
||||
|
||||
## API Reference
|
||||
|
||||
[API reference documentation is on docs.rs](https://docs.rs/bindgen)
|
||||
|
||||
## Environment Variables
|
||||
|
||||
In addition to the [library API](https://docs.rs/bindgen) and [executable command-line API][bindgen-cmdline],
|
||||
`bindgen` can be controlled through environment variables.
|
||||
|
||||
End-users should set these environment variables to modify `bindgen`'s behavior without modifying the source code of direct consumers of `bindgen`.
|
||||
|
||||
- `BINDGEN_EXTRA_CLANG_ARGS`: extra arguments to pass to `clang`
|
||||
- Arguments are whitespace-separated
|
||||
- Use shell-style quoting to pass through whitespace
|
||||
- Examples:
|
||||
- Specify alternate sysroot: `--sysroot=/path/to/sysroot`
|
||||
- Add include search path with spaces: `-I"/path/with spaces"`
|
||||
- `BINDGEN_EXTRA_CLANG_ARGS_<TARGET>`: similar to `BINDGEN_EXTRA_CLANG_ARGS`,
|
||||
but used to set per-target arguments to pass to clang. Useful to set system include
|
||||
directories in a target-specific way in cross-compilation environments with multiple targets.
|
||||
Has precedence over `BINDGEN_EXTRA_CLANG_ARGS`.
|
||||
|
||||
Additionally, `bindgen` uses `libclang` to parse C and C++ header files.
|
||||
To modify how `bindgen` searches for `libclang`, see the [`clang-sys` documentation][clang-sys-env].
|
||||
For more details on how `bindgen` uses `libclang`, see the [`bindgen` users guide][bindgen-book-clang].
|
||||
|
||||
## Releases
|
||||
|
||||
We don't follow a specific release calendar, but if you need a release please
|
||||
file an issue requesting that (ping `@emilio` for increased effectiveness).
|
||||
|
||||
## Contributing
|
||||
|
||||
[See `CONTRIBUTING.md` for hacking on `bindgen`!](./CONTRIBUTING.md)
|
||||
|
||||
[bindgen-cmdline]: https://rust-lang.github.io/rust-bindgen/command-line-usage.html
|
||||
[clang-sys-env]: https://github.com/KyleMayes/clang-sys#environment-variables
|
||||
[bindgen-book-clang]: https://rust-lang.github.io/rust-bindgen/requirements.html#clang
|
||||
90
clamav/libclamav_rust/.cargo/vendor/bindgen/build.rs
vendored
Normal file
90
clamav/libclamav_rust/.cargo/vendor/bindgen/build.rs
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
mod target {
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn main() {
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
|
||||
let mut dst =
|
||||
File::create(Path::new(&out_dir).join("host-target.txt")).unwrap();
|
||||
dst.write_all(env::var("TARGET").unwrap().as_bytes())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
mod testgen {
|
||||
use std::char;
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn main() {
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
let mut dst =
|
||||
File::create(Path::new(&out_dir).join("tests.rs")).unwrap();
|
||||
|
||||
let manifest_dir =
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let headers_dir = manifest_dir.join("tests").join("headers");
|
||||
|
||||
let headers = match fs::read_dir(headers_dir) {
|
||||
Ok(dir) => dir,
|
||||
// We may not have headers directory after packaging.
|
||||
Err(..) => return,
|
||||
};
|
||||
|
||||
let entries =
|
||||
headers.map(|result| result.expect("Couldn't read header file"));
|
||||
|
||||
println!("cargo:rerun-if-changed=tests/headers");
|
||||
|
||||
for entry in entries {
|
||||
match entry.path().extension().and_then(OsStr::to_str) {
|
||||
Some("h") | Some("hpp") => {
|
||||
let func = entry
|
||||
.file_name()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.replace(|c| !char::is_alphanumeric(c), "_")
|
||||
.replace("__", "_")
|
||||
.to_lowercase();
|
||||
writeln!(
|
||||
dst,
|
||||
"test_header!(header_{}, {:?});",
|
||||
func,
|
||||
entry.path(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
dst.flush().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
target::main();
|
||||
testgen::main();
|
||||
|
||||
// On behalf of clang_sys, rebuild ourselves if important configuration
|
||||
// variables change, to ensure that bindings get rebuilt if the
|
||||
// underlying libclang changes.
|
||||
println!("cargo:rerun-if-env-changed=LLVM_CONFIG_PATH");
|
||||
println!("cargo:rerun-if-env-changed=LIBCLANG_PATH");
|
||||
println!("cargo:rerun-if-env-changed=LIBCLANG_STATIC_PATH");
|
||||
println!("cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS");
|
||||
println!(
|
||||
"cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}",
|
||||
std::env::var("TARGET").unwrap()
|
||||
);
|
||||
println!(
|
||||
"cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}",
|
||||
std::env::var("TARGET").unwrap().replace("-", "_")
|
||||
);
|
||||
}
|
||||
65
clamav/libclamav_rust/.cargo/vendor/bindgen/csmith-fuzzing/README.md
vendored
Normal file
65
clamav/libclamav_rust/.cargo/vendor/bindgen/csmith-fuzzing/README.md
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# Fuzzing `bindgen` with `csmith`
|
||||
|
||||
[`csmith`][csmith] generates random C and C++ programs that can be used as test
|
||||
cases for compilers. When testing `bindgen` with `csmith`, we interpret the
|
||||
generated programs as header files, and emit Rust bindings to them. If `bindgen`
|
||||
panics, the emitted bindings won't compile with `rustc`, or the generated layout
|
||||
tests in the bindings fail, then we report an issue containing the test case!
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Running the Fuzzer](#running-the-fuzzer)
|
||||
- [Reporting Issues](#reporting-issues)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Requires `python3`, `csmith`, and `creduce` to be in `$PATH`.
|
||||
|
||||
Many OS package managers have `csmith` and `creduce` packages:
|
||||
|
||||
```
|
||||
$ sudo apt install csmith creduce
|
||||
$ brew install csmith creduce
|
||||
$ # Etc...
|
||||
```
|
||||
|
||||
## Running the Fuzzer
|
||||
|
||||
Run `csmith` and test `bindgen` on the generated test cases with this command:
|
||||
|
||||
```
|
||||
$ ./driver.py
|
||||
```
|
||||
|
||||
The driver will keep running until it encounters an error in `bindgen`.
|
||||
|
||||
Each invocation of `./driver.py` will use its own temporary directories, so
|
||||
running it in multiple terminals in parallel is supported.
|
||||
|
||||
`csmith` is run with `--no-checksum --nomain --max-block-size 1
|
||||
--max-block-depth 1` which disables the `main` function, and makes function
|
||||
bodies as simple as possible as `bindgen` does not care about them, but they
|
||||
cannot be completely disabled in `csmith`. Run `csmith --help` to see what
|
||||
exactly those options do.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
Once the fuzz driver finds a test case that causes some kind of error in
|
||||
`bindgen` or its emitted bindings, it is helpful to
|
||||
[run C-Reduce on the test case][creducing] to remove the parts that are
|
||||
irrelevant to reproducing the error. This is ***very*** helpful for the folks
|
||||
who further investigate the issue and come up with a fix!
|
||||
|
||||
Additionally, mention that you discovered the issue via `csmith` and we will add
|
||||
the `A-csmith` label. You can find all the issues discovered with `csmith`, and
|
||||
related to fuzzing with `csmith`, by looking up
|
||||
[all issues tagged with the `A-csmith` label][csmith-issues].
|
||||
|
||||
[csmith]: https://github.com/csmith-project/csmith
|
||||
[creducing]: ../CONTRIBUTING.md#using-creduce-to-minimize-test-cases
|
||||
[csmith-issues]: https://github.com/rust-lang/rust-bindgen/issues?q=label%3AA-csmith
|
||||
106
clamav/libclamav_rust/.cargo/vendor/bindgen/src/callbacks.rs
vendored
Normal file
106
clamav/libclamav_rust/.cargo/vendor/bindgen/src/callbacks.rs
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
//! A public API for more fine-grained customization of bindgen behavior.
|
||||
|
||||
pub use crate::ir::analysis::DeriveTrait;
|
||||
pub use crate::ir::derive::CanDerive as ImplementsTrait;
|
||||
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
|
||||
pub use crate::ir::int::IntKind;
|
||||
use std::fmt;
|
||||
use std::panic::UnwindSafe;
|
||||
|
||||
/// An enum to allow ignoring parsing of macros.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum MacroParsingBehavior {
|
||||
/// Ignore the macro, generating no code for it, or anything that depends on
|
||||
/// it.
|
||||
Ignore,
|
||||
/// The default behavior bindgen would have otherwise.
|
||||
Default,
|
||||
}
|
||||
|
||||
impl Default for MacroParsingBehavior {
|
||||
fn default() -> Self {
|
||||
MacroParsingBehavior::Default
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to allow configuring different kinds of types in different
|
||||
/// situations.
|
||||
pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
|
||||
/// This function will be run on every macro that is identified.
|
||||
fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior {
|
||||
MacroParsingBehavior::Default
|
||||
}
|
||||
|
||||
/// The integer kind an integer macro should have, given a name and the
|
||||
/// value of that macro, or `None` if you want the default to be chosen.
|
||||
fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> {
|
||||
None
|
||||
}
|
||||
|
||||
/// This will be run on every string macro. The callback cannot influence the further
|
||||
/// treatment of the macro, but may use the value to generate additional code or configuration.
|
||||
fn str_macro(&self, _name: &str, _value: &[u8]) {}
|
||||
|
||||
/// This will be run on every function-like macro. The callback cannot
|
||||
/// influence the further treatment of the macro, but may use the value to
|
||||
/// generate additional code or configuration.
|
||||
///
|
||||
/// The first parameter represents the name and argument list (including the
|
||||
/// parentheses) of the function-like macro. The second parameter represents
|
||||
/// the expansion of the macro as a sequence of tokens.
|
||||
fn func_macro(&self, _name: &str, _value: &[&[u8]]) {}
|
||||
|
||||
/// This function should return whether, given an enum variant
|
||||
/// name, and value, this enum variant will forcibly be a constant.
|
||||
fn enum_variant_behavior(
|
||||
&self,
|
||||
_enum_name: Option<&str>,
|
||||
_original_variant_name: &str,
|
||||
_variant_value: EnumVariantValue,
|
||||
) -> Option<EnumVariantCustomBehavior> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Allows to rename an enum variant, replacing `_original_variant_name`.
|
||||
fn enum_variant_name(
|
||||
&self,
|
||||
_enum_name: Option<&str>,
|
||||
_original_variant_name: &str,
|
||||
_variant_value: EnumVariantValue,
|
||||
) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Allows to rename an item, replacing `_original_item_name`.
|
||||
fn item_name(&self, _original_item_name: &str) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// This will be called on every file inclusion, with the full path of the included file.
|
||||
fn include_file(&self, _filename: &str) {}
|
||||
|
||||
/// This will be called to determine whether a particular blocklisted type
|
||||
/// implements a trait or not. This will be used to implement traits on
|
||||
/// other types containing the blocklisted type.
|
||||
///
|
||||
/// * `None`: use the default behavior
|
||||
/// * `Some(ImplementsTrait::Yes)`: `_name` implements `_derive_trait`
|
||||
/// * `Some(ImplementsTrait::Manually)`: any type including `_name` can't
|
||||
/// derive `_derive_trait` but can implemented it manually
|
||||
/// * `Some(ImplementsTrait::No)`: `_name` doesn't implement `_derive_trait`
|
||||
fn blocklisted_type_implements_trait(
|
||||
&self,
|
||||
_name: &str,
|
||||
_derive_trait: DeriveTrait,
|
||||
) -> Option<ImplementsTrait> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Provide a list of custom derive attributes.
|
||||
///
|
||||
/// If no additional attributes are wanted, this function should return an
|
||||
/// empty `Vec`.
|
||||
fn add_derives(&self, _name: &str) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
2093
clamav/libclamav_rust/.cargo/vendor/bindgen/src/clang.rs
vendored
Normal file
2093
clamav/libclamav_rust/.cargo/vendor/bindgen/src/clang.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
102
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/bitfield_unit.rs
vendored
Normal file
102
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/bitfield_unit.rs
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct __BindgenBitfieldUnit<Storage> {
|
||||
storage: Storage,
|
||||
}
|
||||
|
||||
impl<Storage> __BindgenBitfieldUnit<Storage> {
|
||||
#[inline]
|
||||
pub const fn new(storage: Storage) -> Self {
|
||||
Self { storage }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Storage> __BindgenBitfieldUnit<Storage>
|
||||
where
|
||||
Storage: AsRef<[u8]> + AsMut<[u8]>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn get_bit(&self, index: usize) -> bool {
|
||||
debug_assert!(index / 8 < self.storage.as_ref().len());
|
||||
|
||||
let byte_index = index / 8;
|
||||
let byte = self.storage.as_ref()[byte_index];
|
||||
|
||||
let bit_index = if cfg!(target_endian = "big") {
|
||||
7 - (index % 8)
|
||||
} else {
|
||||
index % 8
|
||||
};
|
||||
|
||||
let mask = 1 << bit_index;
|
||||
|
||||
byte & mask == mask
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_bit(&mut self, index: usize, val: bool) {
|
||||
debug_assert!(index / 8 < self.storage.as_ref().len());
|
||||
|
||||
let byte_index = index / 8;
|
||||
let byte = &mut self.storage.as_mut()[byte_index];
|
||||
|
||||
let bit_index = if cfg!(target_endian = "big") {
|
||||
7 - (index % 8)
|
||||
} else {
|
||||
index % 8
|
||||
};
|
||||
|
||||
let mask = 1 << bit_index;
|
||||
if val {
|
||||
*byte |= mask;
|
||||
} else {
|
||||
*byte &= !mask;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
|
||||
debug_assert!(bit_width <= 64);
|
||||
debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
|
||||
debug_assert!(
|
||||
(bit_offset + (bit_width as usize)) / 8 <=
|
||||
self.storage.as_ref().len()
|
||||
);
|
||||
|
||||
let mut val = 0;
|
||||
|
||||
for i in 0..(bit_width as usize) {
|
||||
if self.get_bit(i + bit_offset) {
|
||||
let index = if cfg!(target_endian = "big") {
|
||||
bit_width as usize - 1 - i
|
||||
} else {
|
||||
i
|
||||
};
|
||||
val |= 1 << index;
|
||||
}
|
||||
}
|
||||
|
||||
val
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
|
||||
debug_assert!(bit_width <= 64);
|
||||
debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
|
||||
debug_assert!(
|
||||
(bit_offset + (bit_width as usize)) / 8 <=
|
||||
self.storage.as_ref().len()
|
||||
);
|
||||
|
||||
for i in 0..(bit_width as usize) {
|
||||
let mask = 1 << i;
|
||||
let val_bit_is_set = val & mask == mask;
|
||||
let index = if cfg!(target_endian = "big") {
|
||||
bit_width as usize - 1 - i
|
||||
} else {
|
||||
i
|
||||
};
|
||||
self.set_bit(index + bit_offset, val_bit_is_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
260
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/bitfield_unit_tests.rs
vendored
Normal file
260
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/bitfield_unit_tests.rs
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
//! Tests for `__BindgenBitfieldUnit`.
|
||||
//!
|
||||
//! Note that bit-fields are allocated right to left (least to most significant
|
||||
//! bits).
|
||||
//!
|
||||
//! From the x86 PS ABI:
|
||||
//!
|
||||
//! ```c
|
||||
//! struct {
|
||||
//! int j : 5;
|
||||
//! int k : 6;
|
||||
//! int m : 7;
|
||||
//! };
|
||||
//! ```
|
||||
//!
|
||||
//! ```ignore
|
||||
//! +------------------------------------------------------------+
|
||||
//! | | | | |
|
||||
//! | padding | m | k | j |
|
||||
//! |31 18|17 11|10 5|4 0|
|
||||
//! +------------------------------------------------------------+
|
||||
//! ```
|
||||
|
||||
use super::bitfield_unit::__BindgenBitfieldUnit;
|
||||
|
||||
#[test]
|
||||
fn bitfield_unit_get_bit() {
|
||||
let unit = __BindgenBitfieldUnit::<[u8; 2]>::new([0b10011101, 0b00011101]);
|
||||
|
||||
let mut bits = vec![];
|
||||
for i in 0..16 {
|
||||
bits.push(unit.get_bit(i));
|
||||
}
|
||||
|
||||
println!();
|
||||
println!("bits = {:?}", bits);
|
||||
assert_eq!(
|
||||
bits,
|
||||
&[
|
||||
// 0b10011101
|
||||
true, false, true, true, true, false, false, true,
|
||||
// 0b00011101
|
||||
true, false, true, true, true, false, false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitfield_unit_set_bit() {
|
||||
let mut unit =
|
||||
__BindgenBitfieldUnit::<[u8; 2]>::new([0b00000000, 0b00000000]);
|
||||
|
||||
for i in 0..16 {
|
||||
if i % 3 == 0 {
|
||||
unit.set_bit(i, true);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..16 {
|
||||
assert_eq!(unit.get_bit(i), i % 3 == 0);
|
||||
}
|
||||
|
||||
let mut unit =
|
||||
__BindgenBitfieldUnit::<[u8; 2]>::new([0b11111111, 0b11111111]);
|
||||
|
||||
for i in 0..16 {
|
||||
if i % 3 == 0 {
|
||||
unit.set_bit(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..16 {
|
||||
assert_eq!(unit.get_bit(i), i % 3 != 0);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! bitfield_unit_get {
|
||||
(
|
||||
$(
|
||||
With $storage:expr , then get($start:expr, $len:expr) is $expected:expr;
|
||||
)*
|
||||
) => {
|
||||
#[test]
|
||||
fn bitfield_unit_get() {
|
||||
$({
|
||||
let expected = $expected;
|
||||
let unit = __BindgenBitfieldUnit::<_>::new($storage);
|
||||
let actual = unit.get($start, $len);
|
||||
|
||||
println!();
|
||||
println!("expected = {:064b}", expected);
|
||||
println!("actual = {:064b}", actual);
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitfield_unit_get! {
|
||||
// Let's just exhaustively test getting the bits from a single byte, since
|
||||
// there are few enough combinations...
|
||||
|
||||
With [0b11100010], then get(0, 1) is 0;
|
||||
With [0b11100010], then get(1, 1) is 1;
|
||||
With [0b11100010], then get(2, 1) is 0;
|
||||
With [0b11100010], then get(3, 1) is 0;
|
||||
With [0b11100010], then get(4, 1) is 0;
|
||||
With [0b11100010], then get(5, 1) is 1;
|
||||
With [0b11100010], then get(6, 1) is 1;
|
||||
With [0b11100010], then get(7, 1) is 1;
|
||||
|
||||
With [0b11100010], then get(0, 2) is 0b10;
|
||||
With [0b11100010], then get(1, 2) is 0b01;
|
||||
With [0b11100010], then get(2, 2) is 0b00;
|
||||
With [0b11100010], then get(3, 2) is 0b00;
|
||||
With [0b11100010], then get(4, 2) is 0b10;
|
||||
With [0b11100010], then get(5, 2) is 0b11;
|
||||
With [0b11100010], then get(6, 2) is 0b11;
|
||||
|
||||
With [0b11100010], then get(0, 3) is 0b010;
|
||||
With [0b11100010], then get(1, 3) is 0b001;
|
||||
With [0b11100010], then get(2, 3) is 0b000;
|
||||
With [0b11100010], then get(3, 3) is 0b100;
|
||||
With [0b11100010], then get(4, 3) is 0b110;
|
||||
With [0b11100010], then get(5, 3) is 0b111;
|
||||
|
||||
With [0b11100010], then get(0, 4) is 0b0010;
|
||||
With [0b11100010], then get(1, 4) is 0b0001;
|
||||
With [0b11100010], then get(2, 4) is 0b1000;
|
||||
With [0b11100010], then get(3, 4) is 0b1100;
|
||||
With [0b11100010], then get(4, 4) is 0b1110;
|
||||
|
||||
With [0b11100010], then get(0, 5) is 0b00010;
|
||||
With [0b11100010], then get(1, 5) is 0b10001;
|
||||
With [0b11100010], then get(2, 5) is 0b11000;
|
||||
With [0b11100010], then get(3, 5) is 0b11100;
|
||||
|
||||
With [0b11100010], then get(0, 6) is 0b100010;
|
||||
With [0b11100010], then get(1, 6) is 0b110001;
|
||||
With [0b11100010], then get(2, 6) is 0b111000;
|
||||
|
||||
With [0b11100010], then get(0, 7) is 0b1100010;
|
||||
With [0b11100010], then get(1, 7) is 0b1110001;
|
||||
|
||||
With [0b11100010], then get(0, 8) is 0b11100010;
|
||||
|
||||
// OK. Now let's test getting bits from across byte boundaries.
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(0, 16) is 0b1111111101010101;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(1, 16) is 0b0111111110101010;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(2, 16) is 0b0011111111010101;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(3, 16) is 0b0001111111101010;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(4, 16) is 0b0000111111110101;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(5, 16) is 0b0000011111111010;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(6, 16) is 0b0000001111111101;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(7, 16) is 0b0000000111111110;
|
||||
|
||||
With [0b01010101, 0b11111111, 0b00000000, 0b11111111],
|
||||
then get(8, 16) is 0b0000000011111111;
|
||||
}
|
||||
|
||||
macro_rules! bitfield_unit_set {
|
||||
(
|
||||
$(
|
||||
set($start:expr, $len:expr, $val:expr) is $expected:expr;
|
||||
)*
|
||||
) => {
|
||||
#[test]
|
||||
fn bitfield_unit_set() {
|
||||
$(
|
||||
let mut unit = __BindgenBitfieldUnit::<[u8; 4]>::new([0, 0, 0, 0]);
|
||||
unit.set($start, $len, $val);
|
||||
let actual = unit.get(0, 32);
|
||||
|
||||
println!();
|
||||
println!("set({}, {}, {:032b}", $start, $len, $val);
|
||||
println!("expected = {:064b}", $expected);
|
||||
println!("actual = {:064b}", actual);
|
||||
|
||||
assert_eq!($expected, actual);
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitfield_unit_set! {
|
||||
// Once again, let's exhaustively test single byte combinations.
|
||||
|
||||
set(0, 1, 0b11111111) is 0b00000001;
|
||||
set(1, 1, 0b11111111) is 0b00000010;
|
||||
set(2, 1, 0b11111111) is 0b00000100;
|
||||
set(3, 1, 0b11111111) is 0b00001000;
|
||||
set(4, 1, 0b11111111) is 0b00010000;
|
||||
set(5, 1, 0b11111111) is 0b00100000;
|
||||
set(6, 1, 0b11111111) is 0b01000000;
|
||||
set(7, 1, 0b11111111) is 0b10000000;
|
||||
|
||||
set(0, 2, 0b11111111) is 0b00000011;
|
||||
set(1, 2, 0b11111111) is 0b00000110;
|
||||
set(2, 2, 0b11111111) is 0b00001100;
|
||||
set(3, 2, 0b11111111) is 0b00011000;
|
||||
set(4, 2, 0b11111111) is 0b00110000;
|
||||
set(5, 2, 0b11111111) is 0b01100000;
|
||||
set(6, 2, 0b11111111) is 0b11000000;
|
||||
|
||||
set(0, 3, 0b11111111) is 0b00000111;
|
||||
set(1, 3, 0b11111111) is 0b00001110;
|
||||
set(2, 3, 0b11111111) is 0b00011100;
|
||||
set(3, 3, 0b11111111) is 0b00111000;
|
||||
set(4, 3, 0b11111111) is 0b01110000;
|
||||
set(5, 3, 0b11111111) is 0b11100000;
|
||||
|
||||
set(0, 4, 0b11111111) is 0b00001111;
|
||||
set(1, 4, 0b11111111) is 0b00011110;
|
||||
set(2, 4, 0b11111111) is 0b00111100;
|
||||
set(3, 4, 0b11111111) is 0b01111000;
|
||||
set(4, 4, 0b11111111) is 0b11110000;
|
||||
|
||||
set(0, 5, 0b11111111) is 0b00011111;
|
||||
set(1, 5, 0b11111111) is 0b00111110;
|
||||
set(2, 5, 0b11111111) is 0b01111100;
|
||||
set(3, 5, 0b11111111) is 0b11111000;
|
||||
|
||||
set(0, 6, 0b11111111) is 0b00111111;
|
||||
set(1, 6, 0b11111111) is 0b01111110;
|
||||
set(2, 6, 0b11111111) is 0b11111100;
|
||||
|
||||
set(0, 7, 0b11111111) is 0b01111111;
|
||||
set(1, 7, 0b11111111) is 0b11111110;
|
||||
|
||||
set(0, 8, 0b11111111) is 0b11111111;
|
||||
|
||||
// And, now let's cross byte boundaries.
|
||||
|
||||
set(0, 16, 0b1111111111111111) is 0b00000000000000001111111111111111;
|
||||
set(1, 16, 0b1111111111111111) is 0b00000000000000011111111111111110;
|
||||
set(2, 16, 0b1111111111111111) is 0b00000000000000111111111111111100;
|
||||
set(3, 16, 0b1111111111111111) is 0b00000000000001111111111111111000;
|
||||
set(4, 16, 0b1111111111111111) is 0b00000000000011111111111111110000;
|
||||
set(5, 16, 0b1111111111111111) is 0b00000000000111111111111111100000;
|
||||
set(6, 16, 0b1111111111111111) is 0b00000000001111111111111111000000;
|
||||
set(7, 16, 0b1111111111111111) is 0b00000000011111111111111110000000;
|
||||
set(8, 16, 0b1111111111111111) is 0b00000000111111111111111100000000;
|
||||
}
|
||||
178
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/dyngen.rs
vendored
Normal file
178
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/dyngen.rs
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
use crate::codegen;
|
||||
use crate::ir::function::Abi;
|
||||
use proc_macro2::Ident;
|
||||
|
||||
/// Used to build the output tokens for dynamic bindings.
|
||||
#[derive(Default)]
|
||||
pub struct DynamicItems {
|
||||
/// Tracks the tokens that will appears inside the library struct -- e.g.:
|
||||
/// ```ignore
|
||||
/// struct Lib {
|
||||
/// __library: ::libloading::Library,
|
||||
/// pub x: Result<unsafe extern ..., ::libloading::Error>, // <- tracks these
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
struct_members: Vec<proc_macro2::TokenStream>,
|
||||
|
||||
/// Tracks the tokens that will appear inside the library struct's implementation, e.g.:
|
||||
///
|
||||
/// ```ignore
|
||||
/// impl Lib {
|
||||
/// ...
|
||||
/// pub unsafe fn foo(&self, ...) { // <- tracks these
|
||||
/// ...
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
struct_implementation: Vec<proc_macro2::TokenStream>,
|
||||
|
||||
/// Tracks the initialization of the fields inside the `::new` constructor of the library
|
||||
/// struct, e.g.:
|
||||
/// ```ignore
|
||||
/// impl Lib {
|
||||
///
|
||||
/// pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
|
||||
/// where
|
||||
/// P: AsRef<::std::ffi::OsStr>,
|
||||
/// {
|
||||
/// ...
|
||||
/// let foo = __library.get(...) ...; // <- tracks these
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
constructor_inits: Vec<proc_macro2::TokenStream>,
|
||||
|
||||
/// Tracks the information that is passed to the library struct at the end of the `::new`
|
||||
/// constructor, e.g.:
|
||||
/// ```ignore
|
||||
/// impl LibFoo {
|
||||
/// pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
|
||||
/// where
|
||||
/// P: AsRef<::std::ffi::OsStr>,
|
||||
/// {
|
||||
/// ...
|
||||
/// Ok(LibFoo {
|
||||
/// __library: __library,
|
||||
/// foo,
|
||||
/// bar, // <- tracks these
|
||||
/// ...
|
||||
/// })
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
init_fields: Vec<proc_macro2::TokenStream>,
|
||||
}
|
||||
|
||||
impl DynamicItems {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn get_tokens(&self, lib_ident: Ident) -> proc_macro2::TokenStream {
|
||||
let struct_members = &self.struct_members;
|
||||
let constructor_inits = &self.constructor_inits;
|
||||
let init_fields = &self.init_fields;
|
||||
let struct_implementation = &self.struct_implementation;
|
||||
|
||||
quote! {
|
||||
extern crate libloading;
|
||||
|
||||
pub struct #lib_ident {
|
||||
__library: ::libloading::Library,
|
||||
#(#struct_members)*
|
||||
}
|
||||
|
||||
impl #lib_ident {
|
||||
pub unsafe fn new<P>(
|
||||
path: P
|
||||
) -> Result<Self, ::libloading::Error>
|
||||
where P: AsRef<::std::ffi::OsStr> {
|
||||
let library = ::libloading::Library::new(path)?;
|
||||
Self::from_library(library)
|
||||
}
|
||||
|
||||
pub unsafe fn from_library<L>(
|
||||
library: L
|
||||
) -> Result<Self, ::libloading::Error>
|
||||
where L: Into<::libloading::Library> {
|
||||
let __library = library.into();
|
||||
#( #constructor_inits )*
|
||||
Ok(#lib_ident {
|
||||
__library,
|
||||
#( #init_fields ),*
|
||||
})
|
||||
}
|
||||
|
||||
#( #struct_implementation )*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
abi: Abi,
|
||||
is_variadic: bool,
|
||||
is_required: bool,
|
||||
args: Vec<proc_macro2::TokenStream>,
|
||||
args_identifiers: Vec<proc_macro2::TokenStream>,
|
||||
ret: proc_macro2::TokenStream,
|
||||
ret_ty: proc_macro2::TokenStream,
|
||||
) {
|
||||
if !is_variadic {
|
||||
assert_eq!(args.len(), args_identifiers.len());
|
||||
}
|
||||
|
||||
let signature = quote! { unsafe extern #abi fn ( #( #args),* ) #ret };
|
||||
let member = if is_required {
|
||||
signature
|
||||
} else {
|
||||
quote! { Result<#signature, ::libloading::Error> }
|
||||
};
|
||||
|
||||
self.struct_members.push(quote! {
|
||||
pub #ident: #member,
|
||||
});
|
||||
|
||||
// N.B: If the signature was required, it won't be wrapped in a Result<...>
|
||||
// and we can simply call it directly.
|
||||
let fn_ = if is_required {
|
||||
quote! { self.#ident }
|
||||
} else {
|
||||
quote! { self.#ident.as_ref().expect("Expected function, got error.") }
|
||||
};
|
||||
let call_body = quote! {
|
||||
(#fn_)(#( #args_identifiers ),*)
|
||||
};
|
||||
|
||||
// We can't implement variadic functions from C easily, so we allow to
|
||||
// access the function pointer so that the user can call it just fine.
|
||||
if !is_variadic {
|
||||
self.struct_implementation.push(quote! {
|
||||
pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
|
||||
#call_body
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// N.B: Unwrap the signature upon construction if it is required to be resolved.
|
||||
let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string());
|
||||
self.constructor_inits.push(if is_required {
|
||||
quote! {
|
||||
let #ident = __library.get(#ident_str).map(|sym| *sym)?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
let #ident = __library.get(#ident_str).map(|sym| *sym);
|
||||
}
|
||||
});
|
||||
|
||||
self.init_fields.push(quote! {
|
||||
#ident
|
||||
});
|
||||
}
|
||||
}
|
||||
33
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/error.rs
vendored
Normal file
33
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/error.rs
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
||||
/// Errors that can occur during code generation.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
/// Tried to generate an opaque blob for a type that did not have a layout.
|
||||
NoLayoutForOpaqueBlob,
|
||||
|
||||
/// Tried to instantiate an opaque template definition, or a template
|
||||
/// definition that is too difficult for us to understand (like a partial
|
||||
/// template specialization).
|
||||
InstantiationOfOpaqueType,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
Error::NoLayoutForOpaqueBlob => {
|
||||
"Tried to generate an opaque blob, but had no layout"
|
||||
}
|
||||
Error::InstantiationOfOpaqueType => {
|
||||
"Instantiation of opaque template type or partial template \
|
||||
specialization"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
|
||||
/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
299
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/helpers.rs
vendored
Normal file
299
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/helpers.rs
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
//! Helpers for code generation that don't need macro expansion.
|
||||
|
||||
use crate::ir::context::BindgenContext;
|
||||
use crate::ir::layout::Layout;
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::TokenStreamExt;
|
||||
|
||||
pub mod attributes {
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn repr(which: &str) -> TokenStream {
|
||||
let which = Ident::new(which, Span::call_site());
|
||||
quote! {
|
||||
#[repr( #which )]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repr_list(which_ones: &[&str]) -> TokenStream {
|
||||
let which_ones = which_ones
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|one| TokenStream::from_str(one).expect("repr to be valid"));
|
||||
quote! {
|
||||
#[repr( #( #which_ones ),* )]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derives(which_ones: &[&str]) -> TokenStream {
|
||||
let which_ones = which_ones
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|one| Ident::new(one, Span::call_site()));
|
||||
quote! {
|
||||
#[derive( #( #which_ones ),* )]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inline() -> TokenStream {
|
||||
quote! {
|
||||
#[inline]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn must_use() -> TokenStream {
|
||||
quote! {
|
||||
#[must_use]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn non_exhaustive() -> TokenStream {
|
||||
quote! {
|
||||
#[non_exhaustive]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn doc(comment: String) -> TokenStream {
|
||||
// NOTE(emilio): By this point comments are already preprocessed and in
|
||||
// `///` form. Quote turns them into `#[doc]` comments, but oh well.
|
||||
TokenStream::from_str(&comment).unwrap()
|
||||
}
|
||||
|
||||
pub fn link_name(name: &str) -> TokenStream {
|
||||
// LLVM mangles the name by default but it's already mangled.
|
||||
// Prefixing the name with \u{1} should tell LLVM to not mangle it.
|
||||
let name = format!("\u{1}{}", name);
|
||||
quote! {
|
||||
#[link_name = #name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a proper type for a field or type with a given `Layout`, that is,
|
||||
/// a type with the correct size and alignment restrictions.
|
||||
pub fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream {
|
||||
let opaque = layout.opaque();
|
||||
|
||||
// FIXME(emilio, #412): We fall back to byte alignment, but there are
|
||||
// some things that legitimately are more than 8-byte aligned.
|
||||
//
|
||||
// Eventually we should be able to `unwrap` here, but...
|
||||
let ty_name = match opaque.known_rust_type_for_array(ctx) {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
warn!("Found unknown alignment on code generation!");
|
||||
"u8"
|
||||
}
|
||||
};
|
||||
|
||||
let ty_name = Ident::new(ty_name, Span::call_site());
|
||||
|
||||
let data_len = opaque.array_size(ctx).unwrap_or(layout.size);
|
||||
|
||||
if data_len == 1 {
|
||||
quote! {
|
||||
#ty_name
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
[ #ty_name ; #data_len ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Integer type of the same size as the given `Layout`.
|
||||
pub fn integer_type(
|
||||
ctx: &BindgenContext,
|
||||
layout: Layout,
|
||||
) -> Option<TokenStream> {
|
||||
let name = Layout::known_type_for_size(ctx, layout.size)?;
|
||||
let name = Ident::new(name, Span::call_site());
|
||||
Some(quote! { #name })
|
||||
}
|
||||
|
||||
/// Generates a bitfield allocation unit type for a type with the given `Layout`.
|
||||
pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> TokenStream {
|
||||
let mut tokens = quote! {};
|
||||
|
||||
if ctx.options().enable_cxx_namespaces {
|
||||
tokens.append_all(quote! { root:: });
|
||||
}
|
||||
|
||||
let size = layout.size;
|
||||
tokens.append_all(quote! {
|
||||
__BindgenBitfieldUnit<[u8; #size]>
|
||||
});
|
||||
|
||||
tokens
|
||||
}
|
||||
|
||||
pub mod ast_ty {
|
||||
use crate::ir::context::BindgenContext;
|
||||
use crate::ir::function::FunctionSig;
|
||||
use crate::ir::layout::Layout;
|
||||
use crate::ir::ty::FloatKind;
|
||||
use proc_macro2::{self, TokenStream};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn c_void(ctx: &BindgenContext) -> TokenStream {
|
||||
// ctypes_prefix takes precedence
|
||||
match ctx.options().ctypes_prefix {
|
||||
Some(ref prefix) => {
|
||||
let prefix = TokenStream::from_str(prefix.as_str()).unwrap();
|
||||
quote! {
|
||||
#prefix::c_void
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if ctx.options().use_core &&
|
||||
ctx.options().rust_features.core_ffi_c_void
|
||||
{
|
||||
quote! { ::core::ffi::c_void }
|
||||
} else {
|
||||
quote! { ::std::os::raw::c_void }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw_type(ctx: &BindgenContext, name: &str) -> TokenStream {
|
||||
let ident = ctx.rust_ident_raw(name);
|
||||
match ctx.options().ctypes_prefix {
|
||||
Some(ref prefix) => {
|
||||
let prefix = TokenStream::from_str(prefix.as_str()).unwrap();
|
||||
quote! {
|
||||
#prefix::#ident
|
||||
}
|
||||
}
|
||||
None => quote! {
|
||||
::std::os::raw::#ident
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float_kind_rust_type(
|
||||
ctx: &BindgenContext,
|
||||
fk: FloatKind,
|
||||
layout: Option<Layout>,
|
||||
) -> TokenStream {
|
||||
// TODO: we probably should take the type layout into account more
|
||||
// often?
|
||||
//
|
||||
// Also, maybe this one shouldn't be the default?
|
||||
match (fk, ctx.options().convert_floats) {
|
||||
(FloatKind::Float, true) => quote! { f32 },
|
||||
(FloatKind::Double, true) => quote! { f64 },
|
||||
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
|
||||
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
|
||||
(FloatKind::LongDouble, _) => {
|
||||
match layout {
|
||||
Some(layout) => {
|
||||
match layout.size {
|
||||
4 => quote! { f32 },
|
||||
8 => quote! { f64 },
|
||||
// TODO(emilio): If rust ever gains f128 we should
|
||||
// use it here and below.
|
||||
_ => super::integer_type(ctx, layout)
|
||||
.unwrap_or(quote! { f64 }),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"How didn't we know the layout for a primitive type?"
|
||||
);
|
||||
quote! { f64 }
|
||||
}
|
||||
}
|
||||
}
|
||||
(FloatKind::Float128, _) => {
|
||||
if ctx.options().rust_features.i128_and_u128 {
|
||||
quote! { u128 }
|
||||
} else {
|
||||
quote! { [u64; 2] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn int_expr(val: i64) -> TokenStream {
|
||||
// Don't use quote! { #val } because that adds the type suffix.
|
||||
let val = proc_macro2::Literal::i64_unsuffixed(val);
|
||||
quote!(#val)
|
||||
}
|
||||
|
||||
pub fn uint_expr(val: u64) -> TokenStream {
|
||||
// Don't use quote! { #val } because that adds the type suffix.
|
||||
let val = proc_macro2::Literal::u64_unsuffixed(val);
|
||||
quote!(#val)
|
||||
}
|
||||
|
||||
pub fn byte_array_expr(bytes: &[u8]) -> TokenStream {
|
||||
let mut bytes: Vec<_> = bytes.to_vec();
|
||||
bytes.push(0);
|
||||
quote! { [ #(#bytes),* ] }
|
||||
}
|
||||
|
||||
pub fn cstr_expr(mut string: String) -> TokenStream {
|
||||
string.push('\0');
|
||||
let b = proc_macro2::Literal::byte_string(string.as_bytes());
|
||||
quote! {
|
||||
#b
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float_expr(ctx: &BindgenContext, f: f64) -> Result<TokenStream, ()> {
|
||||
if f.is_finite() {
|
||||
let val = proc_macro2::Literal::f64_unsuffixed(f);
|
||||
|
||||
return Ok(quote!(#val));
|
||||
}
|
||||
|
||||
let prefix = ctx.trait_prefix();
|
||||
|
||||
if f.is_nan() {
|
||||
return Ok(quote! {
|
||||
::#prefix::f64::NAN
|
||||
});
|
||||
}
|
||||
|
||||
if f.is_infinite() {
|
||||
return Ok(if f.is_sign_positive() {
|
||||
quote! {
|
||||
::#prefix::f64::INFINITY
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
::#prefix::f64::NEG_INFINITY
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
warn!("Unknown non-finite float number: {:?}", f);
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn arguments_from_signature(
|
||||
signature: &FunctionSig,
|
||||
ctx: &BindgenContext,
|
||||
) -> Vec<TokenStream> {
|
||||
let mut unnamed_arguments = 0;
|
||||
signature
|
||||
.argument_types()
|
||||
.iter()
|
||||
.map(|&(ref name, _ty)| match *name {
|
||||
Some(ref name) => {
|
||||
let name = ctx.rust_ident(name);
|
||||
quote! { #name }
|
||||
}
|
||||
None => {
|
||||
unnamed_arguments += 1;
|
||||
let name =
|
||||
ctx.rust_ident(format!("arg{}", unnamed_arguments));
|
||||
quote! { #name }
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
245
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/impl_debug.rs
vendored
Normal file
245
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/impl_debug.rs
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
use crate::ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods};
|
||||
use crate::ir::context::BindgenContext;
|
||||
use crate::ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName};
|
||||
use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
|
||||
|
||||
pub fn gen_debug_impl(
|
||||
ctx: &BindgenContext,
|
||||
fields: &[Field],
|
||||
item: &Item,
|
||||
kind: CompKind,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let struct_name = item.canonical_name(ctx);
|
||||
let mut format_string = format!("{} {{{{ ", struct_name);
|
||||
let mut tokens = vec![];
|
||||
|
||||
if item.is_opaque(ctx, &()) {
|
||||
format_string.push_str("opaque");
|
||||
} else {
|
||||
match kind {
|
||||
CompKind::Union => {
|
||||
format_string.push_str("union");
|
||||
}
|
||||
CompKind::Struct => {
|
||||
let processed_fields = fields.iter().filter_map(|f| match f {
|
||||
Field::DataMember(ref fd) => fd.impl_debug(ctx, ()),
|
||||
Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
|
||||
});
|
||||
|
||||
for (i, (fstring, toks)) in processed_fields.enumerate() {
|
||||
if i > 0 {
|
||||
format_string.push_str(", ");
|
||||
}
|
||||
tokens.extend(toks);
|
||||
format_string.push_str(&fstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format_string.push_str(" }}");
|
||||
tokens.insert(0, quote! { #format_string });
|
||||
|
||||
let prefix = ctx.trait_prefix();
|
||||
|
||||
quote! {
|
||||
fn fmt(&self, f: &mut ::#prefix::fmt::Formatter<'_>) -> ::#prefix ::fmt::Result {
|
||||
write!(f, #( #tokens ),*)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for the things which we can codegen tokens that contribute towards a
|
||||
/// generated `impl Debug`.
|
||||
pub trait ImplDebug<'a> {
|
||||
/// Any extra parameter required by this a particular `ImplDebug` implementation.
|
||||
type Extra;
|
||||
|
||||
/// Generate a format string snippet to be included in the larger `impl Debug`
|
||||
/// format string, and the code to get the format string's interpolation values.
|
||||
fn impl_debug(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
extra: Self::Extra,
|
||||
) -> Option<(String, Vec<proc_macro2::TokenStream>)>;
|
||||
}
|
||||
|
||||
impl<'a> ImplDebug<'a> for FieldData {
|
||||
type Extra = ();
|
||||
|
||||
fn impl_debug(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
_: Self::Extra,
|
||||
) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
|
||||
if let Some(name) = self.name() {
|
||||
ctx.resolve_item(self.ty()).impl_debug(ctx, name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ImplDebug<'a> for BitfieldUnit {
|
||||
type Extra = ();
|
||||
|
||||
fn impl_debug(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
_: Self::Extra,
|
||||
) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
|
||||
let mut format_string = String::new();
|
||||
let mut tokens = vec![];
|
||||
for (i, bitfield) in self.bitfields().iter().enumerate() {
|
||||
if i > 0 {
|
||||
format_string.push_str(", ");
|
||||
}
|
||||
|
||||
if let Some(bitfield_name) = bitfield.name() {
|
||||
format_string.push_str(&format!("{} : {{:?}}", bitfield_name));
|
||||
let getter_name = bitfield.getter_name();
|
||||
let name_ident = ctx.rust_ident_raw(getter_name);
|
||||
tokens.push(quote! {
|
||||
self.#name_ident ()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Some((format_string, tokens))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ImplDebug<'a> for Item {
|
||||
type Extra = &'a str;
|
||||
|
||||
fn impl_debug(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
name: &str,
|
||||
) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
|
||||
let name_ident = ctx.rust_ident(name);
|
||||
|
||||
// We don't know if blocklisted items `impl Debug` or not, so we can't
|
||||
// add them to the format string we're building up.
|
||||
if !ctx.allowlisted_items().contains(&self.id()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ty = match self.as_type() {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
fn debug_print(
|
||||
name: &str,
|
||||
name_ident: proc_macro2::TokenStream,
|
||||
) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
|
||||
Some((
|
||||
format!("{}: {{:?}}", name),
|
||||
vec![quote! {
|
||||
self.#name_ident
|
||||
}],
|
||||
))
|
||||
}
|
||||
|
||||
match *ty.kind() {
|
||||
// Handle the simple cases.
|
||||
TypeKind::Void |
|
||||
TypeKind::NullPtr |
|
||||
TypeKind::Int(..) |
|
||||
TypeKind::Float(..) |
|
||||
TypeKind::Complex(..) |
|
||||
TypeKind::Function(..) |
|
||||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
TypeKind::ObjCId |
|
||||
TypeKind::Comp(..) |
|
||||
TypeKind::ObjCSel => debug_print(name, quote! { #name_ident }),
|
||||
|
||||
TypeKind::TemplateInstantiation(ref inst) => {
|
||||
if inst.is_opaque(ctx, self) {
|
||||
Some((format!("{}: opaque", name), vec![]))
|
||||
} else {
|
||||
debug_print(name, quote! { #name_ident })
|
||||
}
|
||||
}
|
||||
|
||||
// The generic is not required to implement Debug, so we can not debug print that type
|
||||
TypeKind::TypeParam => {
|
||||
Some((format!("{}: Non-debuggable generic", name), vec![]))
|
||||
}
|
||||
|
||||
TypeKind::Array(_, len) => {
|
||||
// Generics are not required to implement Debug
|
||||
if self.has_type_param_in_array(ctx) {
|
||||
Some((
|
||||
format!("{}: Array with length {}", name, len),
|
||||
vec![],
|
||||
))
|
||||
} else if len < RUST_DERIVE_IN_ARRAY_LIMIT ||
|
||||
ctx.options().rust_features().larger_arrays
|
||||
{
|
||||
// The simple case
|
||||
debug_print(name, quote! { #name_ident })
|
||||
} else if ctx.options().use_core {
|
||||
// There is no String in core; reducing field visibility to avoid breaking
|
||||
// no_std setups.
|
||||
Some((format!("{}: [...]", name), vec![]))
|
||||
} else {
|
||||
// Let's implement our own print function
|
||||
Some((
|
||||
format!("{}: [{{}}]", name),
|
||||
vec![quote! {
|
||||
self.#name_ident
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
|
||||
.collect::<String>()
|
||||
}],
|
||||
))
|
||||
}
|
||||
}
|
||||
TypeKind::Vector(_, len) => {
|
||||
if ctx.options().use_core {
|
||||
// There is no format! in core; reducing field visibility to avoid breaking
|
||||
// no_std setups.
|
||||
Some((format!("{}(...)", name), vec![]))
|
||||
} else {
|
||||
let self_ids = 0..len;
|
||||
Some((
|
||||
format!("{}({{}})", name),
|
||||
vec![quote! {
|
||||
#(format!("{:?}", self.#self_ids)),*
|
||||
}],
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
// We follow the aliases
|
||||
ctx.resolve_item(t).impl_debug(ctx, name)
|
||||
}
|
||||
|
||||
TypeKind::Pointer(inner) => {
|
||||
let inner_type = ctx.resolve_type(inner).canonical_type(ctx);
|
||||
match *inner_type.kind() {
|
||||
TypeKind::Function(ref sig)
|
||||
if !sig.function_pointers_can_derive() =>
|
||||
{
|
||||
Some((format!("{}: FunctionPointer", name), vec![]))
|
||||
}
|
||||
_ => debug_print(name, quote! { #name_ident }),
|
||||
}
|
||||
}
|
||||
|
||||
TypeKind::Opaque => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
142
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/impl_partialeq.rs
vendored
Normal file
142
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/impl_partialeq.rs
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
use crate::ir::comp::{CompInfo, CompKind, Field, FieldMethods};
|
||||
use crate::ir::context::BindgenContext;
|
||||
use crate::ir::item::{IsOpaque, Item};
|
||||
use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
|
||||
|
||||
/// Generate a manual implementation of `PartialEq` trait for the
|
||||
/// specified compound type.
|
||||
pub fn gen_partialeq_impl(
|
||||
ctx: &BindgenContext,
|
||||
comp_info: &CompInfo,
|
||||
item: &Item,
|
||||
ty_for_impl: &proc_macro2::TokenStream,
|
||||
) -> Option<proc_macro2::TokenStream> {
|
||||
let mut tokens = vec![];
|
||||
|
||||
if item.is_opaque(ctx, &()) {
|
||||
tokens.push(quote! {
|
||||
&self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
|
||||
});
|
||||
} else if comp_info.kind() == CompKind::Union {
|
||||
assert!(!ctx.options().rust_features().untagged_union);
|
||||
tokens.push(quote! {
|
||||
&self.bindgen_union_field[..] == &other.bindgen_union_field[..]
|
||||
});
|
||||
} else {
|
||||
for base in comp_info.base_members().iter() {
|
||||
if !base.requires_storage(ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let ty_item = ctx.resolve_item(base.ty);
|
||||
let field_name = &base.field_name;
|
||||
|
||||
if ty_item.is_opaque(ctx, &()) {
|
||||
let field_name = ctx.rust_ident(field_name);
|
||||
tokens.push(quote! {
|
||||
&self. #field_name [..] == &other. #field_name [..]
|
||||
});
|
||||
} else {
|
||||
tokens.push(gen_field(ctx, ty_item, field_name));
|
||||
}
|
||||
}
|
||||
|
||||
for field in comp_info.fields() {
|
||||
match *field {
|
||||
Field::DataMember(ref fd) => {
|
||||
let ty_item = ctx.resolve_item(fd.ty());
|
||||
let name = fd.name().unwrap();
|
||||
tokens.push(gen_field(ctx, ty_item, name));
|
||||
}
|
||||
Field::Bitfields(ref bu) => {
|
||||
for bitfield in bu.bitfields() {
|
||||
if bitfield.name().is_some() {
|
||||
let getter_name = bitfield.getter_name();
|
||||
let name_ident = ctx.rust_ident_raw(getter_name);
|
||||
tokens.push(quote! {
|
||||
self.#name_ident () == other.#name_ident ()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(quote! {
|
||||
fn eq(&self, other: & #ty_for_impl) -> bool {
|
||||
#( #tokens )&&*
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn gen_field(
|
||||
ctx: &BindgenContext,
|
||||
ty_item: &Item,
|
||||
name: &str,
|
||||
) -> proc_macro2::TokenStream {
|
||||
fn quote_equals(
|
||||
name_ident: proc_macro2::Ident,
|
||||
) -> proc_macro2::TokenStream {
|
||||
quote! { self.#name_ident == other.#name_ident }
|
||||
}
|
||||
|
||||
let name_ident = ctx.rust_ident(name);
|
||||
let ty = ty_item.expect_type();
|
||||
|
||||
match *ty.kind() {
|
||||
TypeKind::Void |
|
||||
TypeKind::NullPtr |
|
||||
TypeKind::Int(..) |
|
||||
TypeKind::Complex(..) |
|
||||
TypeKind::Float(..) |
|
||||
TypeKind::Enum(..) |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
TypeKind::ObjCId |
|
||||
TypeKind::ObjCSel |
|
||||
TypeKind::Comp(..) |
|
||||
TypeKind::Pointer(_) |
|
||||
TypeKind::Function(..) |
|
||||
TypeKind::Opaque => quote_equals(name_ident),
|
||||
|
||||
TypeKind::TemplateInstantiation(ref inst) => {
|
||||
if inst.is_opaque(ctx, ty_item) {
|
||||
quote! {
|
||||
&self. #name_ident [..] == &other. #name_ident [..]
|
||||
}
|
||||
} else {
|
||||
quote_equals(name_ident)
|
||||
}
|
||||
}
|
||||
|
||||
TypeKind::Array(_, len) => {
|
||||
if len <= RUST_DERIVE_IN_ARRAY_LIMIT ||
|
||||
ctx.options().rust_features().larger_arrays
|
||||
{
|
||||
quote_equals(name_ident)
|
||||
} else {
|
||||
quote! {
|
||||
&self. #name_ident [..] == &other. #name_ident [..]
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Vector(_, len) => {
|
||||
let self_ids = 0..len;
|
||||
let other_ids = 0..len;
|
||||
quote! {
|
||||
#(self.#self_ids == other.#other_ids &&)* true
|
||||
}
|
||||
}
|
||||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
let inner_item = ctx.resolve_item(t);
|
||||
gen_field(ctx, inner_item, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
4835
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/mod.rs
vendored
Normal file
4835
clamav/libclamav_rust/.cargo/vendor/bindgen/src/codegen/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user