add openvr, update deps
parent
4525750fe7
commit
14ae060a30
|
@ -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",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
|
|
|
@ -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"}
|
|
@ -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",
|
||||
],
|
||||
)
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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(),
|
|
@ -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
|
|
@ -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));
|
|
@ -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 }
|
||||
}
|
||||
}
|
|
@ -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![];
|
|
@ -269,8 +269,8 @@ impl Builder {
|
|||
};
|
||||
Some(Searcher {
|
||||
config: self.config.clone(),
|
||||
patterns: patterns,
|
||||
rabinkarp: rabinkarp,
|
||||
patterns,
|
||||
rabinkarp,
|
||||
search_kind,
|
||||
minimum_len,
|
||||
})
|
|
@ -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 {
|
|
@ -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
|
|
@ -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
|
|
@ -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,
|
|
@ -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"}
|
|
@ -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
|
@ -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",
|
|
@ -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"
|
|
@ -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"]
|
|
@ -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(())
|
|
@ -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 {
|
|
@ -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
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
@ -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"]
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue