add openvr, update deps

ecs
q3k 2020-03-16 23:30:09 +01:00
parent 4525750fe7
commit 14ae060a30
669 changed files with 56233 additions and 7911 deletions

View File

@ -20,6 +20,10 @@ alias(
name = "log",
actual = "//third_party/cargo/vendor/log-0.4.8:log",
)
alias(
name = "openvr",
actual = "//third_party/cargo/vendor/openvr-0.6.0:openvr",
)
alias(
name = "vulkano",
actual = "//third_party/cargo/vendor/vulkano-0.11.1:vulkano",

787
third_party/cargo/Cargo.lock generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ vulkano = "0.11.1"
vulkano-win = "0.11.1"
winit = "0.18.0"
cgmath = "0.17.0"
openvr = "0.6.0"
[raze]
workspace_path = "//third_party/cargo"

View File

@ -0,0 +1 @@
{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"bf3140f591d5e16e2c178bfdc39bc2ea9fecf3b50963ff60343d3e5a68d024cc","DESIGN.md":"9065f33d818d1562244d36dc4781e2a351108030cee17f11c2ba512ca7b4c27e","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"f679a3a8fa99694e00e2ed8ec9cd6f7dc28eee36f47c472411744aabb0556d0b","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"46c57a83a75a8f25fdf19a15deae10748d12b8af9445ae74700a546a92024608","src/automaton.rs":"ea3fc2648e026eac9f9969b0d457e49af7b4a40044379ce010d054f22afbc98f","src/buffer.rs":"0641828d1058b9c1c16e8e2445ce05c94b0ad2d97736a7e3cd8b913fa8edd7fd","src/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/classes.rs":"166c9f15c9a2e370e2bc9a9e1620bb2db13df52edfde9a0db1f20144519a7e72","src/dfa.rs":"e34f485a7c3257d2edee16fcdb2a5586aa0d2aa9e34d624288eb2b5a0f7cc65b","src/error.rs":"36dbf2cefbfaa8a69186551320dbff023d3e82780a6c925e87c3e3997b967e66","src/lib.rs":"a2a65d72cbe1eed1964c3fb080e5fa54245ab208a3c855531c1036f05e073452","src/nfa.rs":"6e8fe7633033c378e5487604a2772af3fc2eca011fe374fe0b6d6cee98198f58","src/packed/api.rs":"6c65dfa177b7d7b79f90a048f260bec7f817126c693b85f49704c7d2ecf5f646","src/packed/mod.rs":"29c76ad3cbb1f831140cefac7a27fb504ac4af4f454975a571965b48aad417eb","src/packed/pattern.rs":"b88c57af057997da0a5a06f4c5604a7e598c20acfc11c15cd8977727f6e1cf9c","src/packed/rabinkarp.rs":"b3242a8631ea5607163dcbb641e4ac9c6da26774378da1e51651b0ab5656b390","src/packed/teddy/README.md":"5819f40d221af93288e705eadef5393a41d7a0900881b4d676e01fd65d5adf15","src/packed/teddy/compile.rs":"5d7de6a45a84bb2322647a6de7a7b1573837b9222b16e348f023b8d47e0a5130","src/packed/teddy/mod.rs":"f63db3419b1d378929bf0bc1f0e3b909ff3c38b9f2b6e86ba4546b8f39907cd3","src/packed/teddy/runtime.rs":"0a1250ea73159b3be6e0fa9a3f55ecedbb2cb90cb798d1709e9f5ee48f8855d5","src/packed/tests.rs":"0b52ab9eef73a1a4f141f475a9fa98e54d447104aa69acba3a7f8248ce7164b2","src/packed/vector.rs":"ab3c0535fca5f09198d58cbfae44c292aeb3ce44bc92bca36d30dc72963639fc","src/prefilter.rs":"f615e929629f9356fb779a4456a0b6b1ee139960029df71d41620bf3fed9282d","src/state_id.rs":"50958ca2b089d775fb4e49a64950e2f1e8a4af1772fe782ae3715a7745dcc6d7","src/tests.rs":"7458d220c78bbc382c1332e0a222f7e47b6b8ff1fac666d46db4c3a9e63cef4c"},"package":"8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"}

View File

@ -32,15 +32,14 @@ rust_library(
edition = "2015",
srcs = glob(["**/*.rs"]),
deps = [
"//third_party/cargo/vendor/memchr-2.3.0:memchr",
"//third_party/cargo/vendor/memchr-2.3.3:memchr",
],
rustc_flags = [
"--cap-lints=allow",
],
version = "0.7.6",
version = "0.7.10",
crate_features = [
"default",
"memchr",
"std",
],
)

View File

@ -12,7 +12,7 @@
[package]
name = "aho-corasick"
version = "0.7.6"
version = "0.7.10"
authors = ["Andrew Gallant <jamslam@gmail.com>"]
exclude = ["/aho-corasick-debug", "/ci/*", "/.travis.yml", "/appveyor.yml"]
autotests = false
@ -40,8 +40,3 @@ version = "0.3.1"
[features]
default = ["std"]
std = ["memchr/use_std"]
[badges.appveyor]
repository = "BurntSushi/aho-corasick"
[badges.travis-ci]
repository = "BurntSushi/aho-corasick"

View File

@ -2,7 +2,7 @@ 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 crate is Rust programmers that have some
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
@ -13,7 +13,7 @@ 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 root with sparse
* 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.)
@ -74,7 +74,7 @@ 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 ocne. This means, generally speaking, adding more patterns to
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.)
@ -277,12 +277,12 @@ 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 is uses more memory and can take longer to builder. 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
As described in the previous section, one of the downsides of using a DFA
is that is 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

View File

@ -8,8 +8,7 @@ which builds a finite state machine for executing searches in linear time.
Features include case insensitive matching, overlapping matches and search &
replace in streams.
[![Linux build status](https://api.travis-ci.org/BurntSushi/aho-corasick.svg)](https://travis-ci.org/BurntSushi/aho-corasick)
[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/aho-corasick?svg=true)](https://ci.appveyor.com/project/BurntSushi/aho-corasick)
[![Build status](https://github.com/BurntSushi/aho-corasick/workflows/ci/badge.svg)](https://github.com/BurntSushi/aho-corasick/actions)
[![](http://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
@ -95,7 +94,6 @@ loading the entire stream into memory first.
```rust
use aho_corasick::AhoCorasick;
# fn example() -> Result<(), ::std::io::Error> {
let patterns = &["fox", "brown", "quick"];
let replace_with = &["sloth", "grey", "slow"];
@ -107,7 +105,6 @@ 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()
```
@ -166,9 +163,14 @@ expression alternation. See `MatchKind` in the docs for more details.
This crate's minimum supported `rustc` version is `1.28.0`.
The current policy is that the minimum Rust version required to use this crate
can be increased in minor version updates. For example, if `crate 1.0` requires
Rust 1.20.0, then `crate 1.0.z` for all values of `z` will also require Rust
1.20.0 or newer. However, `crate 1.y` for `y > 0` may require a newer minimum
version of Rust.
In general, this crate will be conservative with respect to the minimum
supported version of Rust. In general, it will follow the `regex` crate's
policy, since `regex` is an important dependent.
supported version of Rust.
### Future work

View File

@ -28,6 +28,42 @@ use Match;
// 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
@ -39,8 +75,8 @@ use Match;
/// only when at least one match has been observed.
///
/// Every automaton also has one or more match states, such that
/// `Automaton::is_match_state_unchecked(id)` returns `true` if and only if
/// `id` corresponds to a match state.
/// `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.
///
@ -123,20 +159,12 @@ pub trait Automaton {
/// 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.
unsafe fn next_state_unchecked(
&self,
current: Self::ID,
input: u8,
) -> Self::ID;
fn next_state(&self, current: Self::ID, input: u8) -> Self::ID;
/// Like next_state_unchecked, but debug_asserts that the underlying
/// Like next_state, but debug_asserts that the underlying
/// implementation never returns a `fail_id()` for the next state.
unsafe fn next_state_unchecked_no_fail(
&self,
current: Self::ID,
input: u8,
) -> Self::ID {
let next = self.next_state_unchecked(current, input);
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(),
@ -174,7 +202,7 @@ pub trait Automaton {
}
}
// It's important for this to always be inlined. Namely, it's only caller
// 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)]
@ -183,66 +211,49 @@ pub trait Automaton {
prestate: &mut PrefilterState,
prefilter: Option<&dyn Prefilter>,
haystack: &[u8],
at: usize,
mut at: usize,
state_id: &mut Self::ID,
) -> Option<Match> {
// This is necessary for guaranteeing a safe API, since we use the
// state ID below in a function that exhibits UB if called with an
// invalid state ID.
assert!(
self.is_valid(*state_id),
"{} is not a valid state ID",
state_id.to_usize()
);
unsafe {
let start = haystack.as_ptr();
let end = haystack[haystack.len()..].as_ptr();
let mut ptr = haystack[at..].as_ptr();
while ptr < end {
if let Some(pre) = prefilter {
let at = ptr as usize - start as usize;
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) => {
ptr = start.offset(i as isize);
}
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;
}
}
}
// SAFETY: next_state is safe 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 assert above that it is valid), or it
// comes from the return value of next_state, which is also
// guaranteed to be valid.
*state_id = self.next_state_unchecked_no_fail(*state_id, *ptr);
ptr = ptr.offset(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 {
let end = ptr as usize - start as usize;
self.get_match(*state_id, 0, end)
};
}
}
None
// 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
@ -276,7 +287,7 @@ pub trait Automaton {
}
}
// It's important for this to always be inlined. Namely, it's only caller
// 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)]
@ -285,76 +296,58 @@ pub trait Automaton {
prestate: &mut PrefilterState,
prefilter: Option<&dyn Prefilter>,
haystack: &[u8],
at: usize,
mut at: usize,
state_id: &mut Self::ID,
) -> Option<Match> {
debug_assert!(self.match_kind().is_leftmost());
// This is necessary for guaranteeing a safe API, since we use the
// state ID below in a function that exhibits UB if called with an
// invalid state ID.
assert!(
self.is_valid(*state_id),
"{} is not a valid state ID",
state_id.to_usize()
);
if self.anchored() && at > 0 && *state_id == self.start_state() {
return None;
}
unsafe {
let start = haystack.as_ptr();
let end = haystack[haystack.len()..].as_ptr();
let mut ptr = haystack[at..].as_ptr();
let mut last_match = self.get_match(*state_id, 0, at);
while ptr < end {
if let Some(pre) = prefilter {
let at = ptr as usize - start as usize;
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) => {
ptr = start.offset(i as isize);
}
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;
}
}
}
// SAFETY: next_state is safe 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 assert above that it is valid), or it
// comes from the return value of next_state, which is also
// guaranteed to be valid.
*state_id = self.next_state_unchecked_no_fail(*state_id, *ptr);
ptr = ptr.offset(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(),
"failure state should only be seen after match"
);
return last_match;
}
let end = ptr as usize - start as usize;
last_match = self.get_match(*state_id, 0, end);
}
}
last_match
// 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(),
"failure 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
@ -393,7 +386,7 @@ pub trait Automaton {
}
}
// It's important for this to always be inlined. Namely, it's only caller
// 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)]
@ -402,7 +395,7 @@ pub trait Automaton {
prestate: &mut PrefilterState,
prefilter: Option<&dyn Prefilter>,
haystack: &[u8],
at: usize,
mut at: usize,
) -> Option<Match> {
debug_assert!(self.match_kind().is_leftmost());
if self.anchored() && at > 0 {
@ -422,63 +415,54 @@ pub trait Automaton {
};
}
}
let mut state_id = self.start_state();
unsafe {
let start = haystack.as_ptr();
let end = haystack[haystack.len()..].as_ptr();
let mut ptr = haystack[at..].as_ptr();
let mut last_match = self.get_match(state_id, 0, at);
while ptr < end {
if let Some(pre) = prefilter {
let at = ptr as usize - start as usize;
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) => {
ptr = start.offset(i as isize);
}
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;
}
}
}
// SAFETY: next_state is safe 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 assert above that it is valid), or it
// comes from the return value of next_state, which is also
// guaranteed to be valid.
state_id = self.next_state_unchecked_no_fail(state_id, *ptr);
ptr = ptr.offset(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(),
"failure state should only be seen after match"
);
return last_match;
}
let end = ptr as usize - start as usize;
last_match = self.get_match(state_id, 0, end);
}
}
last_match
// 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(),
"failure 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.

View File

@ -117,6 +117,8 @@ impl Buffer {
// 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(),

View File

@ -36,7 +36,7 @@ impl ByteClasses {
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.
unsafe { *self.0.get_unchecked(byte as usize) }
self.0[byte as usize]
}
/// Return the total number of elements in the alphabet represented by

View File

@ -189,9 +189,9 @@ impl<S: StateID> Automaton for Standard<S> {
self.repr().match_count(id)
}
unsafe fn next_state_unchecked(&self, current: S, input: u8) -> S {
fn next_state(&self, current: S, input: u8) -> S {
let o = current.to_usize() * 256 + input as usize;
*self.repr().trans.get_unchecked(o)
self.repr().trans[o]
}
}
@ -248,11 +248,11 @@ impl<S: StateID> Automaton for ByteClass<S> {
self.repr().match_count(id)
}
unsafe fn next_state_unchecked(&self, current: S, input: u8) -> S {
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.get_unchecked(o)
self.repr().trans[o]
}
}
@ -317,9 +317,9 @@ impl<S: StateID> Automaton for Premultiplied<S> {
self.repr().matches[o].len()
}
unsafe fn next_state_unchecked(&self, current: S, input: u8) -> S {
fn next_state(&self, current: S, input: u8) -> S {
let o = current.to_usize() + input as usize;
*self.repr().trans.get_unchecked(o)
self.repr().trans[o]
}
}
@ -384,10 +384,10 @@ impl<S: StateID> Automaton for PremultipliedByteClass<S> {
self.repr().matches[o].len()
}
unsafe fn next_state_unchecked(&self, current: S, input: u8) -> S {
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.get_unchecked(o)
self.repr().trans[o]
}
}
@ -637,8 +637,8 @@ impl Builder {
heap_bytes: 0,
prefilter: nfa.prefilter_obj().map(|p| p.clone()),
byte_classes: byte_classes.clone(),
trans: trans,
matches: matches,
trans,
matches,
};
for id in (0..nfa.state_len()).map(S::from_usize) {
repr.matches[id.to_usize()].extend_from_slice(nfa.matches(id));

View File

@ -292,6 +292,6 @@ impl Match {
#[inline]
fn from_span(id: usize, start: usize, end: usize) -> Match {
Match { pattern: id, len: end - start, end: end }
Match { pattern: id, len: end - start, end }
}
}

View File

@ -194,7 +194,7 @@ impl<S: StateID> NFA<S> {
trans,
// Anchored automatons do not have any failure transitions.
fail: if self.anchored { dead_id() } else { self.start_id },
depth: depth,
depth,
matches: vec![],
});
Ok(id)
@ -207,7 +207,7 @@ impl<S: StateID> NFA<S> {
trans,
// Anchored automatons do not have any failure transitions.
fail: if self.anchored { dead_id() } else { self.start_id },
depth: depth,
depth,
matches: vec![],
});
Ok(id)
@ -262,14 +262,14 @@ impl<S: StateID> Automaton for NFA<S> {
self.states[id.to_usize()].matches.len()
}
unsafe fn next_state_unchecked(&self, mut current: S, input: u8) -> S {
fn next_state(&self, mut current: S, input: u8) -> S {
// This terminates since:
//
// 1. `State.fail` never points to fail_id().
// 2. All `State.fail` values point to a state closer to `start`.
// 3. The start state has no transitions to fail_id().
loop {
let state = self.states.get_unchecked(current.to_usize());
let state = &self.states[current.to_usize()];
let next = state.next_state(input);
if next != fail_id() {
return next;
@ -335,9 +335,9 @@ impl<S: StateID> State<S> {
/// Represents the transitions for a single dense state.
///
/// The primary purpose here is to encapsulate unchecked index access. Namely,
/// since a dense representation always contains 256 elements, all values of
/// `u8` are valid indices.
/// The primary purpose here is to encapsulate index access. Namely, since a
/// dense representation always contains 256 elements, all values of `u8` are
/// valid indices.
#[derive(Clone, Debug)]
struct Dense<S>(Vec<S>);
@ -362,7 +362,7 @@ impl<S> Index<u8> for Dense<S> {
fn index(&self, i: u8) -> &S {
// SAFETY: This is safe because all dense transitions have
// exactly 256 elements, so all u8 values are valid indices.
unsafe { self.0.get_unchecked(i as usize) }
&self.0[i as usize]
}
}
@ -371,7 +371,7 @@ impl<S> IndexMut<u8> for Dense<S> {
fn index_mut(&mut self, i: u8) -> &mut S {
// SAFETY: This is safe because all dense transitions have
// exactly 256 elements, so all u8 values are valid indices.
unsafe { self.0.get_unchecked_mut(i as usize) }
&mut self.0[i as usize]
}
}
@ -619,7 +619,7 @@ struct Compiler<'a, S: StateID> {
impl<'a, S: StateID> Compiler<'a, S> {
fn new(builder: &'a Builder) -> Result<Compiler<'a, S>> {
Ok(Compiler {
builder: builder,
builder,
prefilter: prefilter::Builder::new(builder.match_kind)
.ascii_case_insensitive(builder.ascii_case_insensitive),
nfa: NFA {
@ -702,6 +702,10 @@ impl<'a, S: StateID> Compiler<'a, S> {
// building a DFA. They would technically be useful for the
// NFA, but it would require a second pass over the patterns.
self.byte_classes.set_range(b, b);
if self.builder.ascii_case_insensitive {
let b = opposite_ascii_case(b);
self.byte_classes.set_range(b, b);
}
// If the transition from prev using the current byte already
// exists, then just move through it. Otherwise, add a new
@ -1259,6 +1263,7 @@ impl<S: StateID> fmt::Debug for NFA<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "NFA(")?;
writeln!(f, "match_kind: {:?}", self.match_kind)?;
writeln!(f, "prefilter: {:?}", self.prefilter)?;
writeln!(f, "{}", "-".repeat(79))?;
for (id, s) in self.states.iter().enumerate() {
let mut trans = vec![];

View File

@ -269,8 +269,8 @@ impl Builder {
};
Some(Searcher {
config: self.config.clone(),
patterns: patterns,
rabinkarp: rabinkarp,
patterns,
rabinkarp,
search_kind,
minimum_len,
})

View File

@ -119,7 +119,7 @@ impl Builder {
// safe to call functions marked with the `avx2` target feature.
match (masks.len(), avx, fat) {
(1, false, _) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddySlim1Mask128(
runtime::TeddySlim1Mask128 {
@ -128,7 +128,7 @@ impl Builder {
),
}),
(1, true, false) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddySlim1Mask256(
runtime::TeddySlim1Mask256 {
@ -137,7 +137,7 @@ impl Builder {
),
}),
(1, true, true) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddyFat1Mask256(
runtime::TeddyFat1Mask256 {
@ -146,7 +146,7 @@ impl Builder {
),
}),
(2, false, _) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddySlim2Mask128(
runtime::TeddySlim2Mask128 {
@ -156,7 +156,7 @@ impl Builder {
),
}),
(2, true, false) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddySlim2Mask256(
runtime::TeddySlim2Mask256 {
@ -166,7 +166,7 @@ impl Builder {
),
}),
(2, true, true) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddyFat2Mask256(
runtime::TeddyFat2Mask256 {
@ -176,7 +176,7 @@ impl Builder {
),
}),
(3, false, _) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddySlim3Mask128(
runtime::TeddySlim3Mask128 {
@ -187,7 +187,7 @@ impl Builder {
),
}),
(3, true, false) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddySlim3Mask256(
runtime::TeddySlim3Mask256 {
@ -198,7 +198,7 @@ impl Builder {
),
}),
(3, true, true) => Some(Teddy {
buckets: buckets,
buckets,
max_pattern_id: patterns.max_pattern_id(),
exec: runtime::Exec::TeddyFat3Mask256(
runtime::TeddyFat3Mask256 {

View File

@ -371,8 +371,14 @@ struct RareBytesBuilder {
/// Whether this prefilter should account for ASCII case insensitivity or
/// not.
ascii_case_insensitive: bool,
/// A set of byte offsets associated with detected rare bytes. An entry is
/// only set if a rare byte is detected in a pattern.
/// A set of rare bytes, indexed by byte value.
rare_set: ByteSet,
/// A set of byte offsets associated with bytes in a pattern. An entry
/// corresponds to a particular bytes (its index) and is only non-zero if
/// the byte occurred at an offset greater than 0 in at least one pattern.
///
/// If a byte's offset is not representable in 8 bits, then the rare bytes
/// prefilter becomes inert.
byte_offsets: RareByteOffsets,
/// Whether this is available as a prefilter or not. This can be set to
/// false during construction if a condition is seen that invalidates the
@ -385,11 +391,43 @@ struct RareBytesBuilder {
rank_sum: u16,
}
/// A set of rare byte offsets, keyed by byte.
/// A set of bytes.
#[derive(Clone, Copy)]
struct ByteSet([bool; 256]);
impl ByteSet {
fn empty() -> ByteSet {
ByteSet([false; 256])
}
fn insert(&mut self, b: u8) -> bool {
let new = !self.contains(b);
self.0[b as usize] = true;
new
}
fn contains(&self, b: u8) -> bool {
self.0[b as usize]
}
}
impl fmt::Debug for ByteSet {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bytes = vec![];
for b in 0..=255 {
if self.contains(b) {
bytes.push(b);
}
}
f.debug_struct("ByteSet").field("set", &bytes).finish()
}
}
/// A set of byte offsets, keyed by byte.
#[derive(Clone, Copy)]
struct RareByteOffsets {
/// When an item in this set has an offset of u8::MAX (255), then it is
/// considered unset.
/// Each entry corresponds to the maximum offset of the corresponding
/// byte across all patterns seen.
set: [RareByteOffset; 256],
}
@ -403,21 +441,9 @@ impl RareByteOffsets {
/// greater than the existing offset, then it overwrites the previous
/// value and returns false. If there is no previous value set, then this
/// sets it and returns true.
///
/// The given offset must be active, otherwise this panics.
pub fn apply(&mut self, byte: u8, off: RareByteOffset) -> bool {
assert!(off.is_active());
let existing = &mut self.set[byte as usize];
if !existing.is_active() {
*existing = off;
true
} else {
if existing.max < off.max {
*existing = off;
}
false
}
pub fn set(&mut self, byte: u8, off: RareByteOffset) {
self.set[byte as usize].max =
cmp::max(self.set[byte as usize].max, off.max);
}
}
@ -425,7 +451,7 @@ impl fmt::Debug for RareByteOffsets {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut offsets = vec![];
for off in self.set.iter() {
if off.is_active() {
if off.max > 0 {
offsets.push(off);
}
}
@ -448,34 +474,28 @@ struct RareByteOffset {
/// ineffective when it is asked to start scanning from a position that it
/// has already scanned past.
///
/// N.B. The maximum value for this is 254. A value of 255 indicates that
/// this is unused. If a rare byte is found at an offset of 255 or greater,
/// then the rare-byte prefilter is disabled for simplicity.
/// Using a `u8` here means that if we ever see a pattern that's longer
/// than 255 bytes, then the entire rare byte prefilter is disabled.
max: u8,
}
impl Default for RareByteOffset {
fn default() -> RareByteOffset {
RareByteOffset { max: u8::MAX }
RareByteOffset { max: 0 }
}
}
impl RareByteOffset {
/// Create a new rare byte offset. If the given offset is too big, then
/// an inactive `RareByteOffset` is returned.
fn new(max: usize) -> RareByteOffset {
if max > (u8::MAX - 1) as usize {
RareByteOffset::default()
/// None is returned. In that case, callers should render the rare bytes
/// prefilter inert.
fn new(max: usize) -> Option<RareByteOffset> {
if max > u8::MAX as usize {
None
} else {
RareByteOffset { max: max as u8 }
Some(RareByteOffset { max: max as u8 })
}
}
/// Returns true if and only if this offset is active. If it's inactive,
/// then it should not be used.
fn is_active(&self) -> bool {
self.max < u8::MAX
}
}
impl RareBytesBuilder {
@ -483,6 +503,7 @@ impl RareBytesBuilder {
fn new() -> RareBytesBuilder {
RareBytesBuilder {
ascii_case_insensitive: false,
rare_set: ByteSet::empty(),
byte_offsets: RareByteOffsets::empty(),
available: true,
count: 0,
@ -507,8 +528,8 @@ impl RareBytesBuilder {
return None;
}
let (mut bytes, mut len) = ([0; 3], 0);
for b in 0..256 {
if self.byte_offsets.set[b].is_active() {
for b in 0..=255 {
if self.rare_set.contains(b) {
bytes[len] = b as u8;
len += 1;
}
@ -539,15 +560,25 @@ impl RareBytesBuilder {
/// All patterns added to an Aho-Corasick automaton should be added to this
/// builder before attempting to construct the prefilter.
fn add(&mut self, bytes: &[u8]) {
// If we've already given up, then do nothing.
if !self.available {
return;
}
// If we've already blown our budget, then don't waste time looking
// for more rare bytes.
if self.count > 3 {
self.available = false;
return;
}
// If the pattern is too long, then our offset table is bunk, so
// give up.
if bytes.len() >= 256 {
self.available = false;
return;
}
let mut rarest = match bytes.get(0) {
None => return,
Some(&b) => (b, 0, freq_rank(b)),
Some(&b) => (b, freq_rank(b)),
};
// The idea here is to look for the rarest byte in each pattern, and
// add that to our set. As a special exception, if we see a byte that
@ -558,33 +589,44 @@ impl RareBytesBuilder {
// were searching for `Sherlock` and `lockjaw`, then this would pick
// `k` for both patterns, resulting in the use of `memchr` instead of
// `memchr2` for `k` and `j`.
let mut found = false;
for (pos, &b) in bytes.iter().enumerate() {
if self.byte_offsets.set[b as usize].is_active() {
self.add_rare_byte(b, pos);
return;
self.set_offset(pos, b);
if found {
continue;
}
if self.rare_set.contains(b) {
found = true;
continue;
}
let rank = freq_rank(b);
if rank < rarest.2 {
rarest = (b, pos, rank);
if rank < rarest.1 {
rarest = (b, rank);
}
}
self.add_rare_byte(rarest.0, rarest.1);
if !found {
self.add_rare_byte(rarest.0);
}
}
fn add_rare_byte(&mut self, byte: u8, pos: usize) {
self.add_one_byte(byte, pos);
fn set_offset(&mut self, pos: usize, byte: u8) {
// This unwrap is OK because pos is never bigger than our max.
let offset = RareByteOffset::new(pos).unwrap();
self.byte_offsets.set(byte, offset);
if self.ascii_case_insensitive {
self.add_one_byte(opposite_ascii_case(byte), pos);
self.byte_offsets.set(opposite_ascii_case(byte), offset);
}
}
fn add_one_byte(&mut self, byte: u8, pos: usize) {
let off = RareByteOffset::new(pos);
if !off.is_active() {
self.available = false;
return;
fn add_rare_byte(&mut self, byte: u8) {
self.add_one_rare_byte(byte);
if self.ascii_case_insensitive {
self.add_one_rare_byte(opposite_ascii_case(byte));
}
if self.byte_offsets.apply(byte, off) {
}
fn add_one_rare_byte(&mut self, byte: u8) {
if self.rare_set.insert(byte) {
self.count += 1;
self.rank_sum += freq_rank(byte) as u16;
}
@ -698,7 +740,7 @@ impl Prefilter for RareBytesThree {
/// matches by reporting all positions corresponding to a particular byte. This
/// generally only takes affect when there are at most 3 distinct possible
/// starting bytes. e.g., the patterns `foo`, `bar`, and `baz` have two
/// distinct starting bytes (`f` and `b`), and this prefiler returns all
/// distinct starting bytes (`f` and `b`), and this prefilter returns all
/// occurrences of either `f` or `b`.
///
/// In some cases, a heuristic frequency analysis may determine that it would

View File

@ -69,18 +69,7 @@ mod private {
/// 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`.)
///
/// # Safety
///
/// This trait is unsafe because the correctness of its implementations may be
/// relied upon by other unsafe code. For example, one possible way to
/// implement this trait incorrectly would be to return a maximum identifier
/// in `max_id` that is greater than the real maximum identifier. This will
/// likely result in wrap-on-overflow semantics in release mode, which can in
/// turn produce incorrect state identifiers. Those state identifiers may then
/// in turn access out-of-bounds memory in an automaton's search routine, where
/// bounds checks are explicitly elided for performance reasons.
pub unsafe trait StateID:
pub trait StateID:
private::Sealed
+ Clone
+ Copy
@ -111,11 +100,11 @@ pub unsafe trait StateID:
/// Return the maximum state identifier supported by this representation.
///
/// Implementors must return a correct bound. Doing otherwise may result
/// in memory unsafety.
/// in unspecified behavior (but will not violate memory safety).
fn max_id() -> usize;
}
unsafe impl StateID for usize {
impl StateID for usize {
#[inline]
fn from_usize(n: usize) -> usize {
n
@ -132,7 +121,7 @@ unsafe impl StateID for usize {
}
}
unsafe impl StateID for u8 {
impl StateID for u8 {
#[inline]
fn from_usize(n: usize) -> u8 {
n as u8
@ -149,7 +138,7 @@ unsafe impl StateID for u8 {
}
}
unsafe impl StateID for u16 {
impl StateID for u16 {
#[inline]
fn from_usize(n: usize) -> u16 {
n as u16
@ -167,7 +156,7 @@ unsafe impl StateID for u16 {
}
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
unsafe impl StateID for u32 {
impl StateID for u32 {
#[inline]
fn from_usize(n: usize) -> u32 {
n as u32
@ -185,7 +174,7 @@ unsafe impl StateID for u32 {
}
#[cfg(target_pointer_width = "64")]
unsafe impl StateID for u64 {
impl StateID for u64 {
#[inline]
fn from_usize(n: usize) -> u64 {
n as u64

View File

@ -549,6 +549,29 @@ const ANCHORED_OVERLAPPING: &'static [SearchTest] = &[
t!(aover360, &["foo", "foofoo"], "foofoo", &[(0, 0, 3), (1, 0, 6)]),
];
/// Tests for ASCII case insensitivity.
///
/// These tests should all have the same behavior regardless of match semantics
/// or whether the search is overlapping.
const ASCII_CASE_INSENSITIVE: &'static [SearchTest] = &[
t!(acasei000, &["a"], "A", &[(0, 0, 1)]),
t!(acasei010, &["Samwise"], "SAMWISE", &[(0, 0, 7)]),
t!(acasei011, &["Samwise"], "SAMWISE.abcd", &[(0, 0, 7)]),
t!(acasei020, &["fOoBaR"], "quux foobar baz", &[(0, 5, 11)]),
];
/// Like ASCII_CASE_INSENSITIVE, but specifically for non-overlapping tests.
const ASCII_CASE_INSENSITIVE_NON_OVERLAPPING: &'static [SearchTest] = &[
t!(acasei000, &["foo", "FOO"], "fOo", &[(0, 0, 3)]),
t!(acasei000, &["FOO", "foo"], "fOo", &[(0, 0, 3)]),
];
/// Like ASCII_CASE_INSENSITIVE, but specifically for overlapping tests.
const ASCII_CASE_INSENSITIVE_OVERLAPPING: &'static [SearchTest] = &[
t!(acasei000, &["foo", "FOO"], "fOo", &[(0, 0, 3), (1, 0, 3)]),
t!(acasei001, &["FOO", "foo"], "fOo", &[(0, 0, 3), (1, 0, 3)]),
];
/// Regression tests that are applied to all Aho-Corasick combinations.
///
/// If regression tests are needed for specific match semantics, then add them
@ -907,6 +930,74 @@ testconfig!(
}
);
// And also write out the test combinations for ASCII case insensitivity.
testconfig!(
acasei_standard_nfa_default,
&[ASCII_CASE_INSENSITIVE],
Standard,
|b: &mut AhoCorasickBuilder| {
b.prefilter(false).ascii_case_insensitive(true);
}
);
testconfig!(
acasei_standard_dfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
Standard,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true).dfa(true);
}
);
testconfig!(
overlapping,
acasei_standard_overlapping_nfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_OVERLAPPING],
Standard,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true);
}
);
testconfig!(
overlapping,
acasei_standard_overlapping_dfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_OVERLAPPING],
Standard,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true).dfa(true);
}
);
testconfig!(
acasei_leftmost_first_nfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
LeftmostFirst,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true);
}
);
testconfig!(
acasei_leftmost_first_dfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
LeftmostFirst,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true).dfa(true);
}
);
testconfig!(
acasei_leftmost_longest_nfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
LeftmostLongest,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true);
}
);
testconfig!(
acasei_leftmost_longest_dfa_default,
&[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
LeftmostLongest,
|b: &mut AhoCorasickBuilder| {
b.ascii_case_insensitive(true).dfa(true);
}
);
#[test]
fn search_tests_have_unique_names() {
let assert = |constname, tests: &[SearchTest]| {
@ -996,6 +1087,45 @@ fn regression_ascii_case_insensitive_no_exponential() {
assert!(ac.find("").is_none());
}
// See: https://github.com/BurntSushi/aho-corasick/issues/53
//
// This test ensures that the rare byte prefilter works in a particular corner
// case. In particular, the shift offset detected for '/' in the patterns below
// was incorrect, leading to a false negative.
#[test]
fn regression_rare_byte_prefilter() {
use AhoCorasick;
let ac = AhoCorasick::new_auto_configured(&["ab/j/", "x/"]);
assert!(ac.is_match("ab/j/"));
}
#[test]
fn regression_case_insensitive_prefilter() {
use AhoCorasickBuilder;
for c in b'a'..b'z' {
for c2 in b'a'..b'z' {
let c = c as char;
let c2 = c2 as char;
let needle = format!("{}{}", c, c2).to_lowercase();
let haystack = needle.to_uppercase();
let ac = AhoCorasickBuilder::new()
.ascii_case_insensitive(true)
.prefilter(true)
.build(&[&needle]);
assert_eq!(
1,
ac.find_iter(&haystack).count(),
"failed to find {:?} in {:?}\n\nautomaton:\n{:?}",
needle,
haystack,
ac,
);
}
}
}
fn run_search_tests<F: FnMut(&SearchTest) -> Vec<Match>>(
which: TestCollection,
mut f: F,

View File

@ -1 +0,0 @@
{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"a2f9a1263aa35a92af4ffc1935b264f062738bc25761aa62b3d582031d6bf5f0","DESIGN.md":"44d4516ef38d60e9638f756baf40bcd9eff1b8e8ce7538a1d8549e02d6605d48","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"626d74e4bdac78d2446c75c722a7e46d0eaa4e506a1068ff693b5abc338a384f","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"46c57a83a75a8f25fdf19a15deae10748d12b8af9445ae74700a546a92024608","src/automaton.rs":"85e79ceb964f824fcceca026abd255980840116704834d70a1b9c44833df299f","src/buffer.rs":"c40992e7d1ba0bac6d1c268d41069aad81f2226686c64192ed888a60f66db8cd","src/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/classes.rs":"590f2e257bf7c630bea3a28d4a1f75c78db7a0802f5921aced017a056146b4e6","src/dfa.rs":"2fb1077edfefd2b7f7e9c0d9df55df1441d4571500a2c45aa5b41960a36441e4","src/error.rs":"36dbf2cefbfaa8a69186551320dbff023d3e82780a6c925e87c3e3997b967e66","src/lib.rs":"028ab998e8f0d1a98650b139bcca83681cbb52545060b9253b76d7e19117b53d","src/nfa.rs":"6bc3479ad37c576bba4bbdc9e3d0c6e69a4b7f0d9a88fcbbf727bf4a9b288494","src/packed/api.rs":"aa89627c7114c057c98ad1c7ab9ce18c6ed55267a6bcf7bc8efb917b6cfe5532","src/packed/mod.rs":"29c76ad3cbb1f831140cefac7a27fb504ac4af4f454975a571965b48aad417eb","src/packed/pattern.rs":"b88c57af057997da0a5a06f4c5604a7e598c20acfc11c15cd8977727f6e1cf9c","src/packed/rabinkarp.rs":"b3242a8631ea5607163dcbb641e4ac9c6da26774378da1e51651b0ab5656b390","src/packed/teddy/README.md":"5819f40d221af93288e705eadef5393a41d7a0900881b4d676e01fd65d5adf15","src/packed/teddy/compile.rs":"21b18cbee9bc33918b85b1dc51a0faed57acb426f61e6b72aeaf69faa7595701","src/packed/teddy/mod.rs":"f63db3419b1d378929bf0bc1f0e3b909ff3c38b9f2b6e86ba4546b8f39907cd3","src/packed/teddy/runtime.rs":"0a1250ea73159b3be6e0fa9a3f55ecedbb2cb90cb798d1709e9f5ee48f8855d5","src/packed/tests.rs":"0b52ab9eef73a1a4f141f475a9fa98e54d447104aa69acba3a7f8248ce7164b2","src/packed/vector.rs":"ab3c0535fca5f09198d58cbfae44c292aeb3ce44bc92bca36d30dc72963639fc","src/prefilter.rs":"3dbe93d85c6fb985a9aea0b5eab003fe81a228e02adba00c8f63a35c3fd246b8","src/state_id.rs":"ebecd7046760e6bd72303f288be93342b446e7fe95f20b5ce23653d802c48b09","src/tests.rs":"9201cc0662bc9a1e8fa15c59e33a18a55ec6b3bd6bbea294d9cace0053bb8d24"},"package":"58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"}

View File

@ -32,7 +32,7 @@ rust_library(
edition = "2015",
srcs = glob(["**/*.rs"]),
deps = [
"//third_party/cargo/vendor/libc-0.2.66:libc",
"//third_party/cargo/vendor/libc-0.2.67:libc",
],
rustc_flags = [
"--cap-lints=allow",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -33,15 +33,15 @@ rust_library(
edition = "2018",
srcs = glob(["**/*.rs"]),
deps = [
"//third_party/cargo/vendor/backtrace-sys-0.1.32:backtrace_sys",
"//third_party/cargo/vendor/backtrace-sys-0.1.34:backtrace_sys",
"//third_party/cargo/vendor/cfg-if-0.1.10:cfg_if",
"//third_party/cargo/vendor/libc-0.2.66:libc",
"//third_party/cargo/vendor/libc-0.2.67:libc",
"//third_party/cargo/vendor/rustc-demangle-0.1.16:rustc_demangle",
],
rustc_flags = [
"--cap-lints=allow",
],
version = "0.3.42",
version = "0.3.45",
crate_features = [
"backtrace-sys",
"dbghelp",

314
third_party/cargo/vendor/backtrace-0.3.45/Cargo.lock generated vendored Normal file
View File

@ -0,0 +1,314 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "addr2line"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gimli 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayvec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "backtrace"
version = "0.3.45"
dependencies = [
"addr2line 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"cpp_demangle 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"findshlibs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"goblin 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "compiler_builtins"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cpp_demangle"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "findshlibs"
version = "0.5.0"
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)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gimli"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "goblin"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"scroll 0.10.1 (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 = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-std-workspace-core"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "scroll"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scroll_derive"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smallvec"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
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 addr2line 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4e698660ed2d0f625c39bb877332b4269668720e330e2aa3d67bb1187a656a"
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
"checksum backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35"
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum compiler_builtins 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "036b035e9ebcd705affece16319223d19f229e2358be6e3b7b094e57193312e6"
"checksum cpp_demangle 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4115af6f575a7bc82c613e9e0ed7cc36a5e4fc3a8b54920dc0c820823a31a0d6"
"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
"checksum findshlibs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1260d61e4fe2a6ab845ffdc426a0bd68ffb240b91cf0ec5a8d1170cec535bd8"
"checksum gimli 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81dd6190aad0f05ddbbf3245c54ed14ca4aa6dd32f22312b70d8f168c3e3e633"
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
"checksum goblin 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0259546d6aed5dd1f4efc3ae663cae62912ceb927c0e96ae1fc8a22ab1516763"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc-std-workspace-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c"
"checksum scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1"
"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28"
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"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"

View File

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "backtrace"
version = "0.3.42"
version = "0.3.45"
authors = ["The Rust Project Developers"]
autoexamples = true
autotests = true
@ -61,11 +61,12 @@ optional = true
default-features = false
[dependencies.backtrace-sys]
version = "0.1.32"
version = "0.1.33"
optional = true
default_features = false
[dependencies.cfg-if]
version = "0.1.6"
version = "0.1.10"
[dependencies.compiler_builtins]
version = "0.1.2"
@ -86,7 +87,7 @@ version = "0.5.0"
optional = true
[dependencies.goblin]
version = "0.1.3"
version = "0.2"
features = ["elf32", "elf64", "mach32", "mach64", "pe32", "pe64", "std"]
optional = true
default-features = false
@ -118,7 +119,7 @@ default = ["std", "libunwind", "libbacktrace", "dladdr", "dbghelp"]
dladdr = []
gimli-symbolize = ["addr2line", "findshlibs", "memmap", "goblin"]
kernel32 = []
libbacktrace = ["backtrace-sys"]
libbacktrace = ["backtrace-sys/backtrace-sys"]
libunwind = []
rustc-dep-of-std = ["backtrace-sys/rustc-dep-of-std", "cfg-if/rustc-dep-of-std", "core", "compiler_builtins", "libc/rustc-dep-of-std", "rustc-demangle/rustc-dep-of-std"]
serialize-rustc = ["rustc-serialize"]

View File

@ -57,7 +57,6 @@ impl<'a, 'b> BacktraceFmt<'a, 'b> {
/// sumbolicated later, and otherwise this should just be the first method
/// you call after creating a `BacktraceFmt`.
pub fn add_context(&mut self) -> fmt::Result {
self.fmt.write_str("stack backtrace:\n")?;
#[cfg(target_os = "fuchsia")]
fuchsia::print_dso_context(self.fmt)?;
Ok(())

View File

@ -158,6 +158,7 @@ cfg_if::cfg_if! {
struct Object<'a> {
macho: MachO<'a>,
dwarf: Option<usize>,
syms: Vec<(&'a str, u64)>,
}
impl<'a> Object<'a> {
@ -171,7 +172,16 @@ cfg_if::cfg_if! {
.enumerate()
.find(|(_, segment)| segment.name().ok() == Some("__DWARF"))
.map(|p| p.0);
Some(Object { macho, dwarf })
let mut syms = Vec::new();
if let Some(s) = &macho.symbols {
syms = s.iter()
.filter_map(|e| e.ok())
.filter(|(name, nlist)| name.len() > 0 && !nlist.is_undefined())
.map(|(name, nlist)| (name, nlist.n_value))
.collect();
}
syms.sort_unstable_by_key(|(_, addr)| *addr);
Some(Object { macho, dwarf, syms })
}
fn section(&self, name: &str) -> Option<&'a [u8]> {
@ -194,12 +204,13 @@ cfg_if::cfg_if! {
.map(|p| p.1)
}
fn search_symtab<'b>(&'b self, _addr: u64) -> Option<&'b [u8]> {
// So far it seems that we don't need to implement this. Maybe
// `dladdr` on OSX has us covered? Maybe there's not much in the
// symbol table? In any case our relevant tests are passing
// without this being implemented, so let's skip it for now.
None
fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> {
let i = match self.syms.binary_search_by_key(&addr, |(_, addr)| *addr) {
Ok(i) => i,
Err(i) => i.checked_sub(1)?,
};
let (sym, _addr) = self.syms.get(i)?;
Some(sym.as_bytes())
}
}
} else {

View File

@ -489,7 +489,8 @@ cfg_if::cfg_if! {
} else if #[cfg(all(feature = "libbacktrace",
any(unix, all(windows, not(target_vendor = "uwp"), target_env = "gnu")),
not(target_os = "fuchsia"),
not(target_os = "emscripten")))] {
not(target_os = "emscripten"),
not(target_env = "uclibc")))] {
mod libbacktrace;
use self::libbacktrace::resolve as resolve_imp;
use self::libbacktrace::Symbol as SymbolImp;
@ -497,6 +498,7 @@ cfg_if::cfg_if! {
} else if #[cfg(all(unix,
not(target_os = "emscripten"),
not(target_os = "fuchsia"),
not(target_env = "uclibc"),
feature = "dladdr"))] {
mod dladdr_resolve;
use self::dladdr_resolve::resolve as resolve_imp;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,13 +31,14 @@ rust_library(
edition = "2015",
srcs = glob(["**/*.rs"]),
deps = [
"//third_party/cargo/vendor/libc-0.2.66:libc",
"//third_party/cargo/vendor/libc-0.2.67:libc",
],
rustc_flags = [
"--cap-lints=allow",
],
version = "0.1.32",
version = "0.1.34",
crate_features = [
"backtrace-sys",
],
)

View File

@ -12,7 +12,7 @@
[package]
name = "backtrace-sys"
version = "0.1.32"
version = "0.1.34"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
build = "build.rs"
description = "Bindings to the libbacktrace gcc library\n"
@ -36,4 +36,6 @@ default-features = false
version = "1.0.37"
[features]
backtrace-sys = []
default = ["backtrace-sys"]
rustc-dep-of-std = ["core", "compiler_builtins"]

View File

@ -1,4 +1,4 @@
Copyright (c) 2015 The Rust Project Developers
Copyright (c) 2014 Alex Crichton
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated

View File

@ -7,12 +7,14 @@ use std::path::PathBuf;
fn main() {
let target = env::var("TARGET").unwrap();
if target.contains("msvc") || // libbacktrace isn't used on MSVC windows
if !cfg!(feature = "backtrace-sys") || // without this feature, this crate does nothing
target.contains("msvc") || // libbacktrace isn't used on MSVC windows
target.contains("emscripten") || // no way this will ever compile for emscripten
target.contains("cloudabi") ||
target.contains("hermit") ||
target.contains("wasm32") ||
target.contains("fuchsia")
// fuchsia uses external out-of-process symbolization
target.contains("fuchsia") ||
target.contains("uclibc")
{
println!("cargo:rustc-cfg=empty");
return;
@ -29,10 +31,19 @@ fn main() {
.file("src/libbacktrace/dwarf.c")
.file("src/libbacktrace/fileline.c")
.file("src/libbacktrace/posix.c")
.file("src/libbacktrace/read.c")
.file("src/libbacktrace/sort.c")
.file("src/libbacktrace/state.c");
// `mmap` does not exist on Windows, so we use
// the less efficient `read`-based code.
// Using `mmap` on macOS causes weird isseus - see
// https://github.com/rust-lang/rust/pull/45866
if target.contains("windows") || target.contains("darwin") {
build.file("src/libbacktrace/read.c");
} else {
build.file("src/libbacktrace/mmapio.c");
}
// No need to have any symbols reexported form shared objects
build.flag("-fvisibility=hidden");

Some files were not shown because too many files have changed in this diff Show More