Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace other iter().position() instances with memchr #302

Merged
merged 3 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ crc32fast = { version = "1.2", optional = true }
flate2 = { version = "1", optional = true }
indexmap = { version = "1.1", optional = true }
wasmparser = { version = "0.57", optional = true }
memchr = { version = "2.4", default-features = false }

# Internal feature, only used when building as part of libstd, not part of the
# stable interface of this crate.
Expand Down Expand Up @@ -45,7 +46,7 @@ write = ["write_core", "coff", "elf", "macho"]

# Enable things that require libstd.
# Currently, this provides an `Error` implementation.
std = []
std = ["memchr/std"]
# Enable decompression of compressed sections.
# This feature is not required if you want to do your own decompression.
compression = ["flate2", "std"]
Expand Down
2 changes: 1 addition & 1 deletion src/pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ impl<'data> Bytes<'data> {
/// Reads past the null byte, but doesn't return it.
#[inline]
pub fn read_string(&mut self) -> Result<&'data [u8]> {
match self.0.iter().position(|&x| x == 0) {
match memchr::memchr(b'\0', self.0) {
Some(null) => {
// These will never fail.
let bytes = self.read_bytes(null)?;
Expand Down
32 changes: 15 additions & 17 deletions src/read/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,12 @@ impl<'data> ArchiveMember<'data> {
parse_bsd_extended_name(&header.name[3..], data, &mut file_offset, &mut file_size)
.read_error("Invalid archive extended name length")?
} else if header.name[0] == b'/' {
let name_len =
(header.name.iter().position(|&x| x == b' ')).unwrap_or_else(|| header.name.len());
let name_len = memchr::memchr(b' ', &header.name).unwrap_or(header.name.len());
&header.name[..name_len]
} else {
let name_len = (header.name.iter().position(|&x| x == b'/'))
.or_else(|| header.name.iter().position(|&x| x == b' '))
.unwrap_or_else(|| header.name.len());
let name_len = memchr::memchr(b'/', &header.name)
.or_else(|| memchr::memchr(b' ', &header.name))
.unwrap_or(header.name.len());
&header.name[..name_len]
};

Expand Down Expand Up @@ -268,20 +267,19 @@ impl<'data> ArchiveMember<'data> {

// Ignores bytes starting from the first space.
fn parse_u64_digits(digits: &[u8], radix: u32) -> Option<u64> {
let len = digits
.iter()
.position(|&x| x == b' ')
.unwrap_or_else(|| digits.len());
let digits = &digits[..len];
if digits.is_empty() {
if let [b' ', ..] = digits {
return None;
}
let mut result: u64 = 0;
for &c in digits {
let x = (c as char).to_digit(radix)?;
result = result
.checked_mul(u64::from(radix))?
.checked_add(u64::from(x))?;
if c == b' ' {
return Some(result);
} else {
let x = (c as char).to_digit(radix)?;
result = result
.checked_mul(u64::from(radix))?
.checked_add(u64::from(x))?;
}
}
Some(result)
}
Expand All @@ -290,7 +288,7 @@ fn parse_sysv_extended_name<'data>(digits: &[u8], names: &'data [u8]) -> Result<
let offset = parse_u64_digits(digits, 10).ok_or(())?;
let offset = offset.try_into().map_err(|_| ())?;
let name_data = names.get(offset..).ok_or(())?;
let name = match name_data.iter().position(|&x| x == b'/' || x == 0) {
let name = match memchr::memchr2(b'/', b'\0', name_data) {
Some(len) => &name_data[..len],
None => name_data,
};
Expand All @@ -307,7 +305,7 @@ fn parse_bsd_extended_name<'data, R: ReadRef<'data>>(
let len = parse_u64_digits(digits, 10).ok_or(())?;
*size = size.checked_sub(len).ok_or(())?;
let name_data = data.read_bytes(offset, len)?;
let name = match name_data.iter().position(|&x| x == 0) {
let name = match memchr::memchr(b'\0', name_data) {
Some(len) => &name_data[..len],
None => name_data,
};
Expand Down
2 changes: 1 addition & 1 deletion src/read/coff/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ impl pe::ImageSectionHeader {
/// Return the raw section name.
pub fn raw_name(&self) -> &[u8] {
let bytes = &self.name;
match bytes.iter().position(|&x| x == 0) {
match memchr::memchr(b'\0', bytes) {
Some(end) => &bytes[..end],
None => &bytes[..],
}
Expand Down
4 changes: 2 additions & 2 deletions src/read/coff/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl<'data> SymbolTable<'data> {
.read_error("Invalid COFF symbol index")?;
let bytes = bytes_of_slice(entries);
// The name is padded with nulls.
Ok(match bytes.iter().position(|&x| x == 0) {
Ok(match memchr::memchr(b'\0', bytes) {
Some(end) => &bytes[..end],
None => &bytes[..],
})
Expand Down Expand Up @@ -182,7 +182,7 @@ impl pe::ImageSymbol {
.read_error("Invalid COFF symbol name offset")
} else {
// The name is inline and padded with nulls.
Ok(match self.name.iter().position(|&x| x == 0) {
Ok(match memchr::memchr(b'\0', &self.name) {
Some(end) => &self.name[..end],
None => &self.name[..],
})
Expand Down
4 changes: 2 additions & 2 deletions src/read/macho/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ pub trait Section: Debug + Pod {
/// Return the `sectname` bytes up until the null terminator.
fn name(&self) -> &[u8] {
let sectname = &self.sectname()[..];
match sectname.iter().position(|&x| x == 0) {
match memchr::memchr(b'\0', sectname) {
Some(end) => &sectname[..end],
None => sectname,
}
Expand All @@ -254,7 +254,7 @@ pub trait Section: Debug + Pod {
/// Return the `segname` bytes up until the null terminator.
fn segment_name(&self) -> &[u8] {
let segname = &self.segname()[..];
match segname.iter().position(|&x| x == 0) {
match memchr::memchr(b'\0', segname) {
Some(end) => &segname[..end],
None => segname,
}
Expand Down
2 changes: 1 addition & 1 deletion src/read/macho/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ pub trait Segment: Debug + Pod {
/// Return the `segname` bytes up until the null terminator.
fn name(&self) -> &[u8] {
let segname = &self.segname()[..];
match segname.iter().position(|&x| x == 0) {
match memchr::memchr(b'\0', segname) {
Some(end) => &segname[..end],
None => segname,
}
Expand Down