Skip to content

Commit

Permalink
Make usage of memchr more robust
Browse files Browse the repository at this point in the history
Use an iterator adaptor which is tasked with keeping track of indices
for us so we don't have to indice juggle elsewhere.
  • Loading branch information
alexcrichton committed May 6, 2019
1 parent 23ee204 commit 71c01fe
Showing 1 changed file with 31 additions and 15 deletions.
46 changes: 31 additions & 15 deletions src/cargo/sources/registry/index.rs
Expand Up @@ -490,7 +490,7 @@ impl Summaries {
if cfg!(debug_assertions) {
cache_contents = Some(s.raw_data);
} else {
return Ok(Some(s))
return Ok(Some(s));
}
}
Err(e) => {
Expand All @@ -512,15 +512,12 @@ impl Summaries {
ret.raw_data = contents.to_vec();
let mut cache = SummariesCache::default();
hit_closure = true;
let mut start = 0;
for end in memchr::Memchr::new(b'\n', contents) {
for line in split(contents, b'\n') {
// Attempt forwards-compatibility on the index by ignoring
// everything that we ourselves don't understand, that should
// allow future cargo implementations to break the
// interpretation of each line here and older cargo will simply
// ignore the new lines.
let line = &contents[start..end];
start = end + 1;
let summary = match IndexSummary::parse(line, source_id) {
Ok(summary) => summary,
Err(e) => {
Expand Down Expand Up @@ -635,30 +632,24 @@ impl<'a> SummariesCache<'a> {
if *first_byte != CURRENT_CACHE_VERSION {
failure::bail!("looks like a different Cargo's cache, bailing out");
}
let mut iter = memchr::Memchr::new(0, rest);
let mut start = 0;
if let Some(end) = iter.next() {
let update = &rest[start..end];
let mut iter = split(rest, 0);
if let Some(update) = iter.next() {
if update != last_index_update.as_bytes() {
failure::bail!(
"cache out of date: current index ({}) != cache ({})",
last_index_update,
str::from_utf8(update)?,
)
}
start = end + 1;
} else {
failure::bail!("malformed file");
}
let mut ret = SummariesCache::default();
while let Some(version_end) = iter.next() {
let version = &rest[start..version_end];
while let Some(version) = iter.next() {
let version = str::from_utf8(version)?;
let version = Version::parse(version)?;
let summary_end = iter.next().unwrap();
let summary = &rest[version_end + 1..summary_end];
let summary = iter.next().unwrap();
ret.versions.push((version, summary));
start = summary_end + 1;
}
Ok(ret)
}
Expand Down Expand Up @@ -740,3 +731,28 @@ impl IndexSummary {
})
}
}

fn split<'a>(haystack: &'a [u8], needle: u8) -> impl Iterator<Item = &'a [u8]> + 'a {
struct Split<'a> {
haystack: &'a [u8],
needle: u8,
}

impl<'a> Iterator for Split<'a> {
type Item = &'a [u8];

fn next(&mut self) -> Option<&'a [u8]> {
if self.haystack.is_empty() {
return None;
}
let (ret, remaining) = match memchr::memchr(self.needle, self.haystack) {
Some(pos) => (&self.haystack[..pos], &self.haystack[pos + 1..]),
None => (self.haystack, &[][..]),
};
self.haystack = remaining;
Some(ret)
}
}

Split { haystack, needle }
}

0 comments on commit 71c01fe

Please sign in to comment.