fix rust-csv
diff --git a/third_party/rust-csv/.gitignore b/third_party/rust-csv/.gitignore
deleted file mode 100644
index d24edbd..0000000
--- a/third_party/rust-csv/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-.*.swp
-doc
-tags
-examples/ss10pusa.csv
-build
-target
-Cargo.lock
-scratch*
-bench_large/huge
diff --git a/third_party/rust-csv/.travis.yml b/third_party/rust-csv/.travis.yml
deleted file mode 100644
index 13f9444..0000000
--- a/third_party/rust-csv/.travis.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-dist: trusty
-language: rust
-rust:
- - 1.15.0
- - stable
- - beta
- - nightly
-script:
- - ./ci/check-copy cookbook
- - ./ci/check-copy tutorial
- - cargo build --verbose
- - cargo test --verbose
- - cargo test --verbose --manifest-path csv-core/Cargo.toml
- - cargo test --verbose --manifest-path csv-index/Cargo.toml
- - cargo doc
- - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
- cargo bench --verbose --no-run;
- fi
diff --git a/third_party/rust-csv/ci/check-copy b/third_party/rust-csv/ci/check-copy
old mode 100755
new mode 100644
diff --git a/third_party/rust-csv/csv-core/Cargo.toml b/third_party/rust-csv/csv-core/Cargo.toml
index ae55308..ec668b7 100644
--- a/third_party/rust-csv/csv-core/Cargo.toml
+++ b/third_party/rust-csv/csv-core/Cargo.toml
@@ -18,8 +18,11 @@
[lib]
bench = false
-[dependencies]
-memchr = { path = "../rust-memchr", default-features = false }
+#[dependencies]
+#memchr = { version = "1", default-features = false }
+
+[target.'cfg(not(target_env = "sgx"))'.dependencies]
+sgx_trts = { path = "../../../sgx_trts" }
[dev-dependencies]
arrayvec = { version = "0.3", default-features = false }
diff --git a/third_party/rust-csv/csv-core/src/lib.rs b/third_party/rust-csv/csv-core/src/lib.rs
index 2f46213..4b1cee6 100644
--- a/third_party/rust-csv/csv-core/src/lib.rs
+++ b/third_party/rust-csv/csv-core/src/lib.rs
@@ -99,9 +99,10 @@
#![deny(missing_docs)]
#![no_std]
+#![cfg_attr(target_env = "sgx", feature(rustc_private))]
#[cfg(test)]
extern crate arrayvec;
-extern crate memchr;
+extern crate sgx_trts;
pub use reader::{
Reader, ReaderBuilder,
diff --git a/third_party/rust-csv/csv-core/src/writer.rs b/third_party/rust-csv/csv-core/src/writer.rs
index 96b9220..f4f4ca0 100644
--- a/third_party/rust-csv/csv-core/src/writer.rs
+++ b/third_party/rust-csv/csv-core/src/writer.rs
@@ -1,7 +1,7 @@
use core::fmt;
use core::str;
-use memchr::memchr;
+use sgx_trts::memchr::memchr;
use {QuoteStyle, Terminator};
diff --git a/third_party/rust-csv/csv-index/Cargo.toml b/third_party/rust-csv/csv-index/Cargo.toml
index 0dc9f01..f145046 100644
--- a/third_party/rust-csv/csv-index/Cargo.toml
+++ b/third_party/rust-csv/csv-index/Cargo.toml
@@ -19,7 +19,7 @@
bench = false
[dependencies]
-byteorder = { path = "../../byteorder" }
+byteorder = { path = "../../byteorder", version = "1" }
csv = { path = "..", version = "1.0.0-beta.5" }
[profile.release]
diff --git a/third_party/rust-csv/rust-memchr/x86_64-unknown-linux-sgx.json b/third_party/rust-csv/csv-index/x86_64-unknown-linux-sgx.json
similarity index 100%
rename from third_party/rust-csv/rust-memchr/x86_64-unknown-linux-sgx.json
rename to third_party/rust-csv/csv-index/x86_64-unknown-linux-sgx.json
diff --git a/third_party/rust-csv/rust-memchr/.travis.yml b/third_party/rust-csv/rust-memchr/.travis.yml
deleted file mode 100644
index 6c50f81..0000000
--- a/third_party/rust-csv/rust-memchr/.travis.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-language: rust
-rust:
- - 1.12.0
- - stable
- - beta
- - nightly
-script: ci/script.sh
-branches:
- only:
- - master
diff --git a/third_party/rust-csv/rust-memchr/COPYING b/third_party/rust-csv/rust-memchr/COPYING
deleted file mode 100644
index bb9c20a..0000000
--- a/third_party/rust-csv/rust-memchr/COPYING
+++ /dev/null
@@ -1,3 +0,0 @@
-This project is dual-licensed under the Unlicense and MIT licenses.
-
-You may use this code under the terms of either license.
diff --git a/third_party/rust-csv/rust-memchr/Cargo.toml b/third_party/rust-csv/rust-memchr/Cargo.toml
deleted file mode 100644
index 1889b5b..0000000
--- a/third_party/rust-csv/rust-memchr/Cargo.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-[package]
-name = "memchr"
-version = "2.0.1" #:version
-authors = ["Andrew Gallant <jamslam@gmail.com>", "bluss"]
-description = "Safe interface to memchr."
-documentation = "https://docs.rs/memchr/"
-homepage = "https://github.com/BurntSushi/rust-memchr"
-repository = "https://github.com/BurntSushi/rust-memchr"
-readme = "README.md"
-keywords = ["memchr", "char", "scan", "strchr", "string"]
-license = "Unlicense/MIT"
-
-[badges]
-travis-ci = { repository = "BurntSushi/rust-memchr" }
-appveyor = { repository = "BurntSushi/rust-memchr" }
-
-[lib]
-name = "memchr"
-bench = false
-
-[features]
-default = ["use_std", "libc"]
-use_std = ["libc", "libc/use_std"]
-
-[dependencies]
-libc = { version = "0.2.18", default-features = false, optional = true }
-
-[dev-dependencies]
-quickcheck = { version = "0.6", default-features = false }
-
-[profile.test]
-opt-level = 3
diff --git a/third_party/rust-csv/rust-memchr/LICENSE-MIT b/third_party/rust-csv/rust-memchr/LICENSE-MIT
deleted file mode 100644
index 3b0a5dc..0000000
--- a/third_party/rust-csv/rust-memchr/LICENSE-MIT
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Andrew Gallant
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/third_party/rust-csv/rust-memchr/Makefile b/third_party/rust-csv/rust-memchr/Makefile
deleted file mode 100644
index 9f956f4..0000000
--- a/third_party/rust-csv/rust-memchr/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-all:
- echo Nothing to do...
-
-ctags:
- ctags --recurse --options=ctags.rust --languages=Rust
-
-docs:
- cargo doc
- in-dir ./target/doc fix-perms
- rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
-
-push:
- git push origin master
- git push github master
diff --git a/third_party/rust-csv/rust-memchr/README.md b/third_party/rust-csv/rust-memchr/README.md
deleted file mode 100644
index 1e7548e..0000000
--- a/third_party/rust-csv/rust-memchr/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-This crate provides a safe interface `libc`'s `memchr` and `memrchr`.
-This crate also provides fallback implementations when either function is
-unavailable.
-
-[![Build status](https://api.travis-ci.org/BurntSushi/rust-memchr.png)](https://travis-ci.org/BurntSushi/rust-memchr)
-[![Build status](https://ci.appveyor.com/api/projects/status/8i9484t8l4w7uql0/branch/master?svg=true)](https://ci.appveyor.com/project/BurntSushi/rust-memchr/branch/master)
-[![](http://meritbadge.herokuapp.com/memchr)](https://crates.io/crates/memchr)
-
-Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
-
-
-### Documentation
-
-[https://docs.rs/memchr](https://docs.rs/memchr)
-
-### no_std
-
-memchr links to the standard library by default, but you can disable the
-`use_std` feature if you want to use it in a `#![no_std]` crate:
-
-```toml
-[dependencies]
-memchr = { version = "1.0", default-features = false }
-```
-
-### Performance
-
-On my system (Linux/amd64), `memchr` is about an order of magnitude faster than
-the more idiomatic `haystack.iter().position(|&b| b == needle)`:
-
-```
-test iterator ... bench: 5,280 ns/iter (+/- 13) = 1893 MB/s
-test iterator_reversed ... bench: 5,271 ns/iter (+/- 7) = 1897 MB/s
-test libc_memchr ... bench: 202 ns/iter (+/- 0) = 49504 MB/s
-test libc_memrchr ... bench: 197 ns/iter (+/- 1) = 50761 MB/s
-```
diff --git a/third_party/rust-csv/rust-memchr/UNLICENSE b/third_party/rust-csv/rust-memchr/UNLICENSE
deleted file mode 100644
index 68a49da..0000000
--- a/third_party/rust-csv/rust-memchr/UNLICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-This is free and unencumbered software released into the public domain.
-
-Anyone is free to copy, modify, publish, use, compile, sell, or
-distribute this software, either in source code form or as a compiled
-binary, for any purpose, commercial or non-commercial, and by any
-means.
-
-In jurisdictions that recognize copyright laws, the author or authors
-of this software dedicate any and all copyright interest in the
-software to the public domain. We make this dedication for the benefit
-of the public at large and to the detriment of our heirs and
-successors. We intend this dedication to be an overt act of
-relinquishment in perpetuity of all present and future rights to this
-software under copyright law.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-For more information, please refer to <http://unlicense.org/>
diff --git a/third_party/rust-csv/rust-memchr/appveyor.yml b/third_party/rust-csv/rust-memchr/appveyor.yml
deleted file mode 100644
index 8170c78..0000000
--- a/third_party/rust-csv/rust-memchr/appveyor.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-environment:
- matrix:
- - TARGET: x86_64-pc-windows-msvc
- - TARGET: i686-pc-windows-msvc
- - TARGET: i686-pc-windows-gnu
-install:
- - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- - SET PATH=%PATH%;C:\MinGW\bin
- - rustc -V
- - cargo -V
-build: false
-test_script:
- - cargo build --verbose
- - cargo test --verbose
- - cargo bench --verbose
-branches:
- only:
- - master
diff --git a/third_party/rust-csv/rust-memchr/benches/bench.rs b/third_party/rust-csv/rust-memchr/benches/bench.rs
deleted file mode 100644
index 949b222..0000000
--- a/third_party/rust-csv/rust-memchr/benches/bench.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-#![feature(test)]
-
-extern crate memchr;
-extern crate test;
-
-use std::iter;
-
-fn bench_data() -> Vec<u8> { iter::repeat(b'z').take(10000).collect() }
-
-#[bench]
-fn iterator_memchr(b: &mut test::Bencher) {
- let haystack = bench_data();
- let needle = b'a';
- b.iter(|| {
- assert!(haystack.iter().position(|&b| b == needle).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn optimized_memchr(b: &mut test::Bencher) {
- let haystack = bench_data();
- let needle = b'a';
- b.iter(|| {
- assert!(memchr::memchr(needle, &haystack).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn iterator_memrchr(b: &mut test::Bencher) {
- let haystack = bench_data();
- let needle = b'a';
- b.iter(|| {
- assert!(haystack.iter().rposition(|&b| b == needle).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn optimized_memrchr(b: &mut test::Bencher) {
- let haystack = bench_data();
- let needle = b'a';
- b.iter(|| {
- assert!(memchr::memrchr(needle, &haystack).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn iterator_memchr2(b: &mut test::Bencher) {
- let haystack = bench_data();
- let (needle1, needle2) = (b'a', b'b');
- b.iter(|| {
- assert!(haystack.iter().position(|&b| {
- b == needle1 || b == needle2
- }).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn manual_memchr2(b: &mut test::Bencher) {
- fn find_singles(
- sparse: &[bool],
- text: &[u8],
- ) -> Option<(usize, usize)> {
- for (hi, &b) in text.iter().enumerate() {
- if sparse[b as usize] {
- return Some((hi, hi+1));
- }
- }
- None
- }
-
- let haystack = bench_data();
- let mut sparse = vec![false; 256];
- sparse[b'a' as usize] = true;
- sparse[b'b' as usize] = true;
- b.iter(|| {
- assert!(find_singles(&sparse, &haystack).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn optimized_memchr2(b: &mut test::Bencher) {
- let haystack = bench_data();
- let (needle1, needle2) = (b'a', b'b');
- b.iter(|| {
- assert!(memchr::memchr2(needle1, needle2, &haystack).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn iterator_memchr3(b: &mut test::Bencher) {
- let haystack = bench_data();
- let (needle1, needle2, needle3) = (b'a', b'b', b'c');
- b.iter(|| {
- assert!(haystack.iter().position(|&b| {
- b == needle1 || b == needle2 || b == needle3
- }).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
-
-#[bench]
-fn optimized_memchr3(b: &mut test::Bencher) {
- let haystack = bench_data();
- let (needle1, needle2, needle3) = (b'a', b'b', b'c');
- b.iter(|| {
- assert!(memchr::memchr3(
- needle1, needle2, needle3, &haystack).is_none());
- });
- b.bytes = haystack.len() as u64;
-}
diff --git a/third_party/rust-csv/rust-memchr/ci/script.sh b/third_party/rust-csv/rust-memchr/ci/script.sh
deleted file mode 100755
index aebb3bd..0000000
--- a/third_party/rust-csv/rust-memchr/ci/script.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-set -ex
-
-cargo build --verbose
-cargo doc --verbose
-
-# If we're testing on an older version of Rust, then only check that we
-# can build the crate. This is because the dev dependencies might be updated
-# more frequently, and therefore might require a newer version of Rust.
-#
-# This isn't ideal. It's a compromise.
-if [ "$TRAVIS_RUST_VERSION" = "1.12.0" ]; then
- exit
-fi
-
-cargo test --verbose
-if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
- cargo bench --verbose --no-run
-fi
diff --git a/third_party/rust-csv/rust-memchr/ctags.rust b/third_party/rust-csv/rust-memchr/ctags.rust
deleted file mode 100644
index b42edf7..0000000
--- a/third_party/rust-csv/rust-memchr/ctags.rust
+++ /dev/null
@@ -1,11 +0,0 @@
---langdef=Rust
---langmap=Rust:.rs
---regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/
---regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/
---regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/
---regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/
---regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/
---regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/
---regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/
---regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/
---regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/
diff --git a/third_party/rust-csv/rust-memchr/session.vim b/third_party/rust-csv/rust-memchr/session.vim
deleted file mode 100644
index 213c956..0000000
--- a/third_party/rust-csv/rust-memchr/session.vim
+++ /dev/null
@@ -1 +0,0 @@
-au BufWritePost *.rs silent!make ctags > /dev/null 2>&1
diff --git a/third_party/rust-csv/rust-memchr/src/lib.rs b/third_party/rust-csv/rust-memchr/src/lib.rs
deleted file mode 100644
index 764b87d..0000000
--- a/third_party/rust-csv/rust-memchr/src/lib.rs
+++ /dev/null
@@ -1,1062 +0,0 @@
-/*!
-This crate defines two functions, `memchr` and `memrchr`, which expose a safe
-interface to the corresponding functions in `libc`.
-*/
-
-#![deny(missing_docs)]
-#![allow(unused_imports)]
-#![doc(html_root_url = "https://docs.rs/memchr/2.0.0")]
-
-#![cfg_attr(not(feature = "use_std"), no_std)]
-
-#[cfg(all(test, not(feature = "use_std")))]
-#[macro_use]
-extern crate std;
-
-#[cfg(all(feature = "libc", not(target_arch = "wasm32")))]
-extern crate libc;
-
-#[macro_use]
-#[cfg(test)]
-extern crate quickcheck;
-
-#[cfg(all(feature = "libc", not(target_arch = "wasm32")))]
-use libc::c_void;
-#[cfg(all(feature = "libc", not(target_arch = "wasm32")))]
-use libc::{c_int, size_t};
-
-#[cfg(feature = "use_std")]
-use std::cmp;
-#[cfg(not(feature = "use_std"))]
-use core::cmp;
-
-const LO_U64: u64 = 0x0101010101010101;
-const HI_U64: u64 = 0x8080808080808080;
-
-// use truncation
-const LO_USIZE: usize = LO_U64 as usize;
-const HI_USIZE: usize = HI_U64 as usize;
-
-#[cfg(target_pointer_width = "32")]
-const USIZE_BYTES: usize = 4;
-#[cfg(target_pointer_width = "64")]
-const USIZE_BYTES: usize = 8;
-
-/// Return `true` if `x` contains any zero byte.
-///
-/// From *Matters Computational*, J. Arndt
-///
-/// "The idea is to subtract one from each of the bytes and then look for
-/// bytes where the borrow propagated all the way to the most significant
-/// bit."
-#[inline]
-fn contains_zero_byte(x: usize) -> bool {
- x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
-}
-
-#[cfg(target_pointer_width = "32")]
-#[inline]
-fn repeat_byte(b: u8) -> usize {
- let mut rep = (b as usize) << 8 | b as usize;
- rep = rep << 16 | rep;
- rep
-}
-
-#[cfg(target_pointer_width = "64")]
-#[inline]
-fn repeat_byte(b: u8) -> usize {
- let mut rep = (b as usize) << 8 | b as usize;
- rep = rep << 16 | rep;
- rep = rep << 32 | rep;
- rep
-}
-
-macro_rules! iter_next {
- // Common code for the memchr iterators:
- // update haystack and position and produce the index
- //
- // self: &mut Self where Self is the iterator
- // search_result: Option<usize> which is the result of the corresponding
- // memchr function.
- //
- // Returns Option<usize> (the next iterator element)
- ($self_:expr, $search_result:expr) => {
- $search_result.map(move |index| {
- // split and take the remaining back half
- $self_.haystack = $self_.haystack.split_at(index + 1).1;
- let found_position = $self_.position + index;
- $self_.position = found_position + 1;
- found_position
- })
- }
-}
-
-macro_rules! iter_next_back {
- ($self_:expr, $search_result:expr) => {
- $search_result.map(move |index| {
- // split and take the remaining front half
- $self_.haystack = $self_.haystack.split_at(index).0;
- $self_.position + index
- })
- }
-}
-
-/// An iterator for memchr
-pub struct Memchr<'a> {
- needle: u8,
- // The haystack to iterate over
- haystack: &'a [u8],
- // The index
- position: usize,
-}
-
-impl<'a> Memchr<'a> {
- /// Creates a new iterator that yields all positions of needle in haystack.
- pub fn new(needle: u8, haystack: &[u8]) -> Memchr {
- Memchr {
- needle: needle,
- haystack: haystack,
- position: 0,
- }
- }
-}
-
-impl<'a> Iterator for Memchr<'a> {
- type Item = usize;
-
- fn next(&mut self) -> Option<usize> {
- iter_next!(self, memchr(self.needle, &self.haystack))
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (0, Some(self.haystack.len()))
- }
-}
-
-impl<'a> DoubleEndedIterator for Memchr<'a> {
- fn next_back(&mut self) -> Option<Self::Item> {
- iter_next_back!(self, memrchr(self.needle, &self.haystack))
- }
-}
-
-/// A safe interface to `memchr`.
-///
-/// Returns the index corresponding to the first occurrence of `needle` in
-/// `haystack`, or `None` if one is not found.
-///
-/// memchr reduces to super-optimized machine code at around an order of
-/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
-/// (See benchmarks.)
-///
-/// # Example
-///
-/// This shows how to find the first position of a byte in a byte string.
-///
-/// ```rust
-/// use memchr::memchr;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memchr(b'k', haystack), Some(8));
-/// ```
-#[inline(always)] // reduces constant overhead
-pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
- // libc memchr
- #[cfg(all(feature = "libc",
- not(target_arch = "wasm32"),
- any(not(target_os = "windows"),
- not(any(target_pointer_width = "32",
- target_pointer_width = "64")))))]
- #[inline(always)] // reduces constant overhead
- fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- use libc::memchr as libc_memchr;
-
- let p = unsafe {
- libc_memchr(haystack.as_ptr() as *const c_void,
- needle as c_int,
- haystack.len() as size_t)
- };
- if p.is_null() {
- None
- } else {
- Some(p as usize - (haystack.as_ptr() as usize))
- }
- }
-
- // use fallback on windows, since it's faster
- // use fallback on wasm32, since it doesn't have libc
- #[cfg(all(any(not(feature = "libc"), target_os = "windows", target_arch = "wasm32"),
- any(target_pointer_width = "32",
- target_pointer_width = "64")))]
- fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- fallback::memchr(needle, haystack)
- }
-
- // For the rare case of neither 32 bit nor 64-bit platform.
- #[cfg(all(any(not(feature = "libc"), target_os = "windows"),
- not(target_pointer_width = "32"),
- not(target_pointer_width = "64")))]
- fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().position(|&b| b == needle)
- }
-
- memchr_specific(needle, haystack)
-}
-
-/// A safe interface to `memrchr`.
-///
-/// Returns the index corresponding to the last occurrence of `needle` in
-/// `haystack`, or `None` if one is not found.
-///
-/// # Example
-///
-/// This shows how to find the last position of a byte in a byte string.
-///
-/// ```rust
-/// use memchr::memrchr;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memrchr(b'o', haystack), Some(17));
-/// ```
-#[inline(always)] // reduces constant overhead
-pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-
- #[cfg(all(feature = "libc", target_os = "linux"))]
- #[inline(always)] // reduces constant overhead
- fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
- if haystack.is_empty() {
- return None;
- }
- let p = unsafe {
- libc::memrchr(haystack.as_ptr() as *const c_void,
- needle as c_int,
- haystack.len() as size_t)
- };
- if p.is_null() {
- None
- } else {
- Some(p as usize - (haystack.as_ptr() as usize))
- }
- }
-
- #[cfg(all(not(all(feature = "libc", target_os = "linux")),
- any(target_pointer_width = "32", target_pointer_width = "64")))]
- fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- fallback::memrchr(needle, haystack)
- }
-
- // For the rare case of neither 32 bit nor 64-bit platform.
- #[cfg(all(not(all(feature = "libc", target_os = "linux")),
- not(target_pointer_width = "32"),
- not(target_pointer_width = "64")))]
- fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().rposition(|&b| b == needle)
- }
-
- memrchr_specific(needle, haystack)
-}
-
-/// An iterator for Memchr2
-pub struct Memchr2<'a> {
- needle1: u8,
- needle2: u8,
- // The haystack to iterate over
- haystack: &'a [u8],
- // The index
- position: usize,
-}
-
-impl<'a> Memchr2<'a> {
- /// Creates a new iterator that yields all positions of needle in haystack.
- pub fn new(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2 {
- Memchr2 {
- needle1: needle1,
- needle2: needle2,
- haystack: haystack,
- position: 0,
- }
- }
-}
-
-impl<'a> Iterator for Memchr2<'a> {
- type Item = usize;
-
- fn next(&mut self) -> Option<usize> {
- iter_next!(self, memchr2(self.needle1, self.needle2, &self.haystack))
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (0, Some(self.haystack.len()))
- }
-}
-
-
-/// Like `memchr`, but searches for two bytes instead of one.
-pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> {
- fn slow(b1: u8, b2: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().position(|&b| b == b1 || b == b2)
- }
-
- let len = haystack.len();
- let ptr = haystack.as_ptr();
- let align = (ptr as usize) & (USIZE_BYTES - 1);
- let mut i = 0;
- if align > 0 {
- i = cmp::min(USIZE_BYTES - align, len);
- if let Some(found) = slow(needle1, needle2, &haystack[..i]) {
- return Some(found);
- }
- }
- let repeated_b1 = repeat_byte(needle1);
- let repeated_b2 = repeat_byte(needle2);
- if len >= USIZE_BYTES {
- while i <= len - USIZE_BYTES {
- unsafe {
- let u = *(ptr.offset(i as isize) as *const usize);
- let found_ub1 = contains_zero_byte(u ^ repeated_b1);
- let found_ub2 = contains_zero_byte(u ^ repeated_b2);
- if found_ub1 || found_ub2 {
- break;
- }
- }
- i += USIZE_BYTES;
- }
- }
- slow(needle1, needle2, &haystack[i..]).map(|pos| i + pos)
-}
-
-/// An iterator for Memchr3
-pub struct Memchr3<'a> {
- needle1: u8,
- needle2: u8,
- needle3: u8,
- // The haystack to iterate over
- haystack: &'a [u8],
- // The index
- position: usize,
-}
-
-impl<'a> Memchr3<'a> {
- /// Create a new Memchr2 that's initalized to zero with a haystack
- pub fn new(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &[u8],
- ) -> Memchr3 {
- Memchr3 {
- needle1: needle1,
- needle2: needle2,
- needle3: needle3,
- haystack: haystack,
- position: 0,
- }
- }
-}
-
-impl<'a> Iterator for Memchr3<'a> {
- type Item = usize;
-
- fn next(&mut self) -> Option<usize> {
- iter_next!(
- self,
- memchr3(self.needle1, self.needle2, self.needle3, &self.haystack)
- )
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (0, Some(self.haystack.len()))
- }
-}
-
-/// Like `memchr`, but searches for three bytes instead of one.
-pub fn memchr3(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &[u8],
-) -> Option<usize> {
- fn slow(b1: u8, b2: u8, b3: u8, haystack: &[u8]) -> Option<usize> {
- haystack.iter().position(|&b| b == b1 || b == b2 || b == b3)
- }
-
- let len = haystack.len();
- let ptr = haystack.as_ptr();
- let align = (ptr as usize) & (USIZE_BYTES - 1);
- let mut i = 0;
- if align > 0 {
- i = cmp::min(USIZE_BYTES - align, len);
- if let Some(found) = slow(needle1, needle2, needle3, &haystack[..i]) {
- return Some(found);
- }
- }
- let repeated_b1 = repeat_byte(needle1);
- let repeated_b2 = repeat_byte(needle2);
- let repeated_b3 = repeat_byte(needle3);
- if len >= USIZE_BYTES {
- while i <= len - USIZE_BYTES {
- unsafe {
- let u = *(ptr.offset(i as isize) as *const usize);
- let found_ub1 = contains_zero_byte(u ^ repeated_b1);
- let found_ub2 = contains_zero_byte(u ^ repeated_b2);
- let found_ub3 = contains_zero_byte(u ^ repeated_b3);
- if found_ub1 || found_ub2 || found_ub3 {
- break;
- }
- }
- i += USIZE_BYTES;
- }
- }
- slow(needle1, needle2, needle3, &haystack[i..]).map(|pos| i + pos)
-}
-
-#[allow(dead_code)]
-#[cfg(any(test, not(feature = "libc"), all(not(target_os = "linux"),
- any(target_pointer_width = "32", target_pointer_width = "64"))))]
-mod fallback {
- #[cfg(feature = "use_std")]
- use std::cmp;
- #[cfg(not(feature = "use_std"))]
- use core::cmp;
-
- use super::{
- LO_U64, HI_U64, LO_USIZE, HI_USIZE, USIZE_BYTES,
- contains_zero_byte, repeat_byte,
- };
-
- /// Return the first index matching the byte `x` in `text`.
- pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
- // Scan for a single byte value by reading two `usize` words at a time.
- //
- // Split `text` in three parts
- // - unaligned inital part, before first word aligned address in text
- // - body, scan by 2 words at a time
- // - the last remaining part, < 2 word size
- let len = text.len();
- let ptr = text.as_ptr();
-
- // search up to an aligned boundary
- let align = (ptr as usize) & (USIZE_BYTES - 1);
- let mut offset;
- if align > 0 {
- offset = cmp::min(USIZE_BYTES - align, len);
- let pos = text[..offset].iter().position(|elt| *elt == x);
- if let Some(index) = pos {
- return Some(index);
- }
- } else {
- offset = 0;
- }
-
- // search the body of the text
- let repeated_x = repeat_byte(x);
-
- if len >= 2 * USIZE_BYTES {
- while offset <= len - 2 * USIZE_BYTES {
- debug_assert_eq!((ptr as usize + offset) % USIZE_BYTES, 0);
- unsafe {
- let u = *(ptr.offset(offset as isize) as *const usize);
- let v = *(ptr.offset((offset + USIZE_BYTES) as isize) as *const usize);
-
- // break if there is a matching byte
- let zu = contains_zero_byte(u ^ repeated_x);
- let zv = contains_zero_byte(v ^ repeated_x);
- if zu || zv {
- break;
- }
- }
- offset += USIZE_BYTES * 2;
- }
- }
-
- // find the byte after the point the body loop stopped
- text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
- }
-
- /// Return the last index matching the byte `x` in `text`.
- pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
- // Scan for a single byte value by reading two `usize` words at a time.
- //
- // Split `text` in three parts
- // - unaligned tail, after the last word aligned address in text
- // - body, scan by 2 words at a time
- // - the first remaining bytes, < 2 word size
- let len = text.len();
- let ptr = text.as_ptr();
-
- // search to an aligned boundary
- let end_align = (ptr as usize + len) & (USIZE_BYTES - 1);
- let mut offset;
- if end_align > 0 {
- offset = if end_align >= len { 0 } else { len - end_align };
- let pos = text[offset..].iter().rposition(|elt| *elt == x);
- if let Some(index) = pos {
- return Some(offset + index);
- }
- } else {
- offset = len;
- }
-
- // search the body of the text
- let repeated_x = repeat_byte(x);
-
- while offset >= 2 * USIZE_BYTES {
- debug_assert_eq!((ptr as usize + offset) % USIZE_BYTES, 0);
- unsafe {
- let u = *(ptr.offset(offset as isize - 2 * USIZE_BYTES as isize) as *const usize);
- let v = *(ptr.offset(offset as isize - USIZE_BYTES as isize) as *const usize);
-
- // break if there is a matching byte
- let zu = contains_zero_byte(u ^ repeated_x);
- let zv = contains_zero_byte(v ^ repeated_x);
- if zu || zv {
- break;
- }
- }
- offset -= 2 * USIZE_BYTES;
- }
-
- // find the byte before the point the body loop stopped
- text[..offset].iter().rposition(|elt| *elt == x)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::prelude::v1::*;
- use quickcheck;
-
- use super::{memchr, memrchr, memchr2, memchr3, Memchr, Memchr2, Memchr3};
- // Use a macro to test both native and fallback impls on all configurations
- macro_rules! memchr_tests {
- ($mod_name:ident, $memchr:path, $memrchr:path) => {
- mod $mod_name {
- use std::prelude::v1::*;
- use quickcheck;
- #[test]
- fn matches_one() {
- assert_eq!(Some(0), $memchr(b'a', b"a"));
- }
-
- #[test]
- fn matches_begin() {
- assert_eq!(Some(0), $memchr(b'a', b"aaaa"));
- }
-
- #[test]
- fn matches_end() {
- assert_eq!(Some(4), $memchr(b'z', b"aaaaz"));
- }
-
- #[test]
- fn matches_nul() {
- assert_eq!(Some(4), $memchr(b'\x00', b"aaaa\x00"));
- }
-
- #[test]
- fn matches_past_nul() {
- assert_eq!(Some(5), $memchr(b'z', b"aaaa\x00z"));
- }
-
- #[test]
- fn no_match_empty() {
- assert_eq!(None, $memchr(b'a', b""));
- }
-
- #[test]
- fn no_match() {
- assert_eq!(None, $memchr(b'a', b"xyz"));
- }
-
- #[test]
- fn qc_never_fail() {
- fn prop(needle: u8, haystack: Vec<u8>) -> bool {
- $memchr(needle, &haystack); true
- }
- quickcheck::quickcheck(prop as fn(u8, Vec<u8>) -> bool);
- }
-
- #[test]
- fn matches_one_reversed() {
- assert_eq!(Some(0), $memrchr(b'a', b"a"));
- }
-
- #[test]
- fn matches_begin_reversed() {
- assert_eq!(Some(3), $memrchr(b'a', b"aaaa"));
- }
-
- #[test]
- fn matches_end_reversed() {
- assert_eq!(Some(0), $memrchr(b'z', b"zaaaa"));
- }
-
- #[test]
- fn matches_nul_reversed() {
- assert_eq!(Some(4), $memrchr(b'\x00', b"aaaa\x00"));
- }
-
- #[test]
- fn matches_past_nul_reversed() {
- assert_eq!(Some(0), $memrchr(b'z', b"z\x00aaaa"));
- }
-
- #[test]
- fn no_match_empty_reversed() {
- assert_eq!(None, $memrchr(b'a', b""));
- }
-
- #[test]
- fn no_match_reversed() {
- assert_eq!(None, $memrchr(b'a', b"xyz"));
- }
-
- #[test]
- fn qc_never_fail_reversed() {
- fn prop(needle: u8, haystack: Vec<u8>) -> bool {
- $memrchr(needle, &haystack); true
- }
- quickcheck::quickcheck(prop as fn(u8, Vec<u8>) -> bool);
- }
-
- #[test]
- fn qc_correct_memchr() {
- fn prop(v: Vec<u8>, offset: u8) -> bool {
- // test all pointer alignments
- let uoffset = (offset & 0xF) as usize;
- let data = if uoffset <= v.len() {
- &v[uoffset..]
- } else {
- &v[..]
- };
- for byte in 0..256u32 {
- let byte = byte as u8;
- let pos = data.iter().position(|elt| *elt == byte);
- if $memchr(byte, &data) != pos {
- return false;
- }
- }
- true
- }
- quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
- }
-
- #[test]
- fn qc_correct_memrchr() {
- fn prop(v: Vec<u8>, offset: u8) -> bool {
- // test all pointer alignments
- let uoffset = (offset & 0xF) as usize;
- let data = if uoffset <= v.len() {
- &v[uoffset..]
- } else {
- &v[..]
- };
- for byte in 0..256u32 {
- let byte = byte as u8;
- let pos = data.iter().rposition(|elt| *elt == byte);
- if $memrchr(byte, &data) != pos {
- return false;
- }
- }
- true
- }
- quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
- }
- }
- }
- }
-
- memchr_tests! { native, ::memchr, ::memrchr }
- memchr_tests! { fallback, ::fallback::memchr, ::fallback::memrchr }
-
- #[test]
- fn memchr2_matches_one() {
- assert_eq!(Some(0), memchr2(b'a', b'b', b"a"));
- assert_eq!(Some(0), memchr2(b'a', b'b', b"b"));
- assert_eq!(Some(0), memchr2(b'b', b'a', b"a"));
- assert_eq!(Some(0), memchr2(b'b', b'a', b"b"));
- }
-
- #[test]
- fn memchr2_matches_begin() {
- assert_eq!(Some(0), memchr2(b'a', b'b', b"aaaa"));
- assert_eq!(Some(0), memchr2(b'a', b'b', b"bbbb"));
- }
-
- #[test]
- fn memchr2_matches_end() {
- assert_eq!(Some(4), memchr2(b'z', b'y', b"aaaaz"));
- assert_eq!(Some(4), memchr2(b'z', b'y', b"aaaay"));
- }
-
- #[test]
- fn memchr2_matches_nul() {
- assert_eq!(Some(4), memchr2(b'\x00', b'z', b"aaaa\x00"));
- assert_eq!(Some(4), memchr2(b'z', b'\x00', b"aaaa\x00"));
- }
-
- #[test]
- fn memchr2_matches_past_nul() {
- assert_eq!(Some(5), memchr2(b'z', b'y', b"aaaa\x00z"));
- assert_eq!(Some(5), memchr2(b'y', b'z', b"aaaa\x00z"));
- }
-
- #[test]
- fn memchr2_no_match_empty() {
- assert_eq!(None, memchr2(b'a', b'b', b""));
- assert_eq!(None, memchr2(b'b', b'a', b""));
- }
-
- #[test]
- fn memchr2_no_match() {
- assert_eq!(None, memchr2(b'a', b'b', b"xyz"));
- }
-
- #[test]
- fn qc_never_fail_memchr2() {
- fn prop(needle1: u8, needle2: u8, haystack: Vec<u8>) -> bool {
- memchr2(needle1, needle2, &haystack);
- true
- }
- quickcheck::quickcheck(prop as fn(u8, u8, Vec<u8>) -> bool);
- }
-
- #[test]
- fn memchr3_matches_one() {
- assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"a"));
- assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"b"));
- assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"c"));
- }
-
- #[test]
- fn memchr3_matches_begin() {
- assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"aaaa"));
- assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"bbbb"));
- assert_eq!(Some(0), memchr3(b'a', b'b', b'c', b"cccc"));
- }
-
- #[test]
- fn memchr3_matches_end() {
- assert_eq!(Some(4), memchr3(b'z', b'y', b'x', b"aaaaz"));
- assert_eq!(Some(4), memchr3(b'z', b'y', b'x', b"aaaay"));
- assert_eq!(Some(4), memchr3(b'z', b'y', b'x', b"aaaax"));
- }
-
- #[test]
- fn memchr3_matches_nul() {
- assert_eq!(Some(4), memchr3(b'\x00', b'z', b'y', b"aaaa\x00"));
- assert_eq!(Some(4), memchr3(b'z', b'\x00', b'y', b"aaaa\x00"));
- assert_eq!(Some(4), memchr3(b'z', b'y', b'\x00', b"aaaa\x00"));
- }
-
- #[test]
- fn memchr3_matches_past_nul() {
- assert_eq!(Some(5), memchr3(b'z', b'y', b'x', b"aaaa\x00z"));
- assert_eq!(Some(5), memchr3(b'y', b'z', b'x', b"aaaa\x00z"));
- assert_eq!(Some(5), memchr3(b'y', b'x', b'z', b"aaaa\x00z"));
- }
-
- #[test]
- fn memchr3_no_match_empty() {
- assert_eq!(None, memchr3(b'a', b'b', b'c', b""));
- assert_eq!(None, memchr3(b'b', b'a', b'c', b""));
- assert_eq!(None, memchr3(b'c', b'b', b'a', b""));
- }
-
- #[test]
- fn memchr3_no_match() {
- assert_eq!(None, memchr3(b'a', b'b', b'c', b"xyz"));
- }
-
- // return an iterator of the 0-based indices of haystack that match the
- // needle
- fn positions1<'a>(needle: u8, haystack: &'a [u8])
- -> Box<DoubleEndedIterator<Item=usize> + 'a>
- {
- Box::new(haystack.iter()
- .enumerate()
- .filter(move |&(_, &elt)| elt == needle)
- .map(|t| t.0))
- }
-
- fn positions2<'a>(needle1: u8, needle2: u8, haystack: &'a [u8])
- -> Box<DoubleEndedIterator<Item=usize> + 'a>
- {
- Box::new(haystack
- .iter()
- .enumerate()
- .filter(move |&(_, &elt)| elt == needle1 || elt == needle2)
- .map(|t| t.0))
- }
-
- fn positions3<'a>(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: &'a [u8],
- ) -> Box<DoubleEndedIterator<Item=usize> + 'a> {
- Box::new(haystack
- .iter()
- .enumerate()
- .filter(move |&(_, &elt)| {
- elt == needle1 || elt == needle2 || elt == needle3
- })
- .map(|t| t.0))
- }
-
- #[test]
- fn memchr_iter() {
- let haystack = b"aaaabaaaab";
- let mut memchr_iter = Memchr::new(b'b', haystack);
- let first = memchr_iter.next();
- let second = memchr_iter.next();
- let third = memchr_iter.next();
-
- let mut answer_iter = positions1(b'b', haystack);
- assert_eq!(answer_iter.next(), first);
- assert_eq!(answer_iter.next(), second);
- assert_eq!(answer_iter.next(), third);
- }
-
- #[test]
- fn memchr2_iter() {
- let haystack = b"axxb";
- let mut memchr_iter = Memchr2::new(b'a', b'b', haystack);
- let first = memchr_iter.next();
- let second = memchr_iter.next();
- let third = memchr_iter.next();
-
- let mut answer_iter = positions2(b'a', b'b', haystack);
- assert_eq!(answer_iter.next(), first);
- assert_eq!(answer_iter.next(), second);
- assert_eq!(answer_iter.next(), third);
- }
-
- #[test]
- fn memchr3_iter() {
- let haystack = b"axxbc";
- let mut memchr_iter = Memchr3::new(b'a', b'b', b'c', haystack);
- let first = memchr_iter.next();
- let second = memchr_iter.next();
- let third = memchr_iter.next();
- let fourth = memchr_iter.next();
-
- let mut answer_iter = positions3(b'a', b'b', b'c', haystack);
- assert_eq!(answer_iter.next(), first);
- assert_eq!(answer_iter.next(), second);
- assert_eq!(answer_iter.next(), third);
- assert_eq!(answer_iter.next(), fourth);
- }
-
- #[test]
- fn memchr_reverse_iter() {
- let haystack = b"aaaabaaaabaaaab";
- let mut memchr_iter = Memchr::new(b'b', haystack);
- let first = memchr_iter.next();
- let second = memchr_iter.next_back();
- let third = memchr_iter.next();
- let fourth = memchr_iter.next_back();
-
- let mut answer_iter = positions1(b'b', haystack);
- assert_eq!(answer_iter.next(), first);
- assert_eq!(answer_iter.next_back(), second);
- assert_eq!(answer_iter.next(), third);
- assert_eq!(answer_iter.next_back(), fourth);
- }
-
- #[test]
- fn memrchr_iter(){
- let haystack = b"aaaabaaaabaaaab";
- let mut memchr_iter = Memchr::new(b'b', haystack);
- let first = memchr_iter.next_back();
- let second = memchr_iter.next_back();
- let third = memchr_iter.next_back();
- let fourth = memchr_iter.next_back();
-
- let mut answer_iter = positions1(b'b', haystack);
- assert_eq!(answer_iter.next_back(), first);
- assert_eq!(answer_iter.next_back(), second);
- assert_eq!(answer_iter.next_back(), third);
- assert_eq!(answer_iter.next_back(), fourth);
-
- }
-
- #[test]
- fn qc_never_fail_memchr3() {
- fn prop(
- needle1: u8,
- needle2: u8,
- needle3: u8,
- haystack: Vec<u8>,
- ) -> bool {
- memchr3(needle1, needle2, needle3, &haystack);
- true
- }
- quickcheck::quickcheck(prop as fn(u8, u8, u8, Vec<u8>) -> bool);
- }
-
- #[test]
- fn qc_correct_memchr() {
- fn prop(v: Vec<u8>, offset: u8) -> bool {
- // test all pointer alignments
- let uoffset = (offset & 0xF) as usize;
- let data = if uoffset <= v.len() {
- &v[uoffset..]
- } else {
- &v[..]
- };
- for byte in 0..256u32 {
- let byte = byte as u8;
- let pos = data.iter().position(|elt| *elt == byte);
- if memchr(byte, &data) != pos {
- return false;
- }
- }
- true
- }
- quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
- }
-
- #[test]
- fn qc_correct_memrchr() {
- fn prop(v: Vec<u8>, offset: u8) -> bool {
- // test all pointer alignments
- let uoffset = (offset & 0xF) as usize;
- let data = if uoffset <= v.len() {
- &v[uoffset..]
- } else {
- &v[..]
- };
- for byte in 0..256u32 {
- let byte = byte as u8;
- let pos = data.iter().rposition(|elt| *elt == byte);
- if memrchr(byte, &data) != pos {
- return false;
- }
- }
- true
- }
- quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
- }
-
- #[test]
- fn qc_correct_memchr2() {
- fn prop(v: Vec<u8>, offset: u8) -> bool {
- // test all pointer alignments
- let uoffset = (offset & 0xF) as usize;
- let data = if uoffset <= v.len() {
- &v[uoffset..]
- } else {
- &v[..]
- };
- for b1 in 0..256u32 {
- for b2 in 0..256u32 {
- let (b1, b2) = (b1 as u8, b2 as u8);
- let expected = data
- .iter()
- .position(|&b| b == b1 || b == b2);
- let got = memchr2(b1, b2, &data);
- if expected != got {
- return false;
- }
- }
- }
- true
- }
- quickcheck::quickcheck(prop as fn(Vec<u8>, u8) -> bool);
- }
-
- // take items from a DEI, taking front for each true and back for each
- // false. Return a vector with the concatenation of the fronts and the
- // reverse of the backs.
- fn double_ended_take<I, J>(mut iter: I, take_side: J) -> Vec<I::Item>
- where I: DoubleEndedIterator,
- J: Iterator<Item=bool>,
- {
- let mut found_front = Vec::new();
- let mut found_back = Vec::new();
-
- for take_front in take_side {
- if take_front {
- if let Some(pos) = iter.next() {
- found_front.push(pos);
- } else {
- break;
- }
- } else {
- if let Some(pos) = iter.next_back() {
- found_back.push(pos);
- } else {
- break;
- }
- };
- }
-
- let mut all_found = found_front;
- all_found.extend(found_back.into_iter().rev());
- all_found
- }
-
-
- quickcheck! {
- fn qc_memchr_double_ended_iter(needle: u8, data: Vec<u8>,
- take_side: Vec<bool>) -> bool
- {
- // make nonempty
- let mut take_side = take_side;
- if take_side.is_empty() { take_side.push(true) };
-
- let iter = Memchr::new(needle, &data);
- let all_found = double_ended_take(
- iter, take_side.iter().cycle().cloned());
-
- all_found.iter().cloned().eq(positions1(needle, &data))
- }
-
- fn qc_memchr1_iter(data: Vec<u8>) -> bool {
- let needle = 0;
- let answer = positions1(needle, &data);
- answer.eq(Memchr::new(needle, &data))
- }
-
- fn qc_memchr1_rev_iter(data: Vec<u8>) -> bool {
- let needle = 0;
- let answer = positions1(needle, &data);
- answer.rev().eq(Memchr::new(needle, &data).rev())
- }
-
- fn qc_memchr2_iter(data: Vec<u8>) -> bool {
- let needle1 = 0;
- let needle2 = 1;
- let answer = positions2(needle1, needle2, &data);
- answer.eq(Memchr2::new(needle1, needle2, &data))
- }
-
- fn qc_memchr3_iter(data: Vec<u8>) -> bool {
- let needle1 = 0;
- let needle2 = 1;
- let needle3 = 2;
- let answer = positions3(needle1, needle2, needle3, &data);
- answer.eq(Memchr3::new(needle1, needle2, needle3, &data))
- }
-
- fn qc_memchr1_iter_size_hint(data: Vec<u8>) -> bool {
- // test that the size hint is within reasonable bounds
- let needle = 0;
- let mut iter = Memchr::new(needle, &data);
- let mut real_count = data
- .iter()
- .filter(|&&elt| elt == needle)
- .count();
-
- while let Some(index) = iter.next() {
- real_count -= 1;
- let (lower, upper) = iter.size_hint();
- assert!(lower <= real_count);
- assert!(upper.unwrap() >= real_count);
- assert!(upper.unwrap() <= data.len() - index);
- }
- true
- }
- }
-}
diff --git a/third_party/rust-csv/scripts/copy-examples b/third_party/rust-csv/scripts/copy-examples
old mode 100755
new mode 100644