Skip to content

Commit 71c01fe

Browse files
committed
Make usage of memchr more robust
Use an iterator adaptor which is tasked with keeping track of indices for us so we don't have to indice juggle elsewhere.
1 parent 23ee204 commit 71c01fe

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

src/cargo/sources/registry/index.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ impl Summaries {
490490
if cfg!(debug_assertions) {
491491
cache_contents = Some(s.raw_data);
492492
} else {
493-
return Ok(Some(s))
493+
return Ok(Some(s));
494494
}
495495
}
496496
Err(e) => {
@@ -512,15 +512,12 @@ impl Summaries {
512512
ret.raw_data = contents.to_vec();
513513
let mut cache = SummariesCache::default();
514514
hit_closure = true;
515-
let mut start = 0;
516-
for end in memchr::Memchr::new(b'\n', contents) {
515+
for line in split(contents, b'\n') {
517516
// Attempt forwards-compatibility on the index by ignoring
518517
// everything that we ourselves don't understand, that should
519518
// allow future cargo implementations to break the
520519
// interpretation of each line here and older cargo will simply
521520
// ignore the new lines.
522-
let line = &contents[start..end];
523-
start = end + 1;
524521
let summary = match IndexSummary::parse(line, source_id) {
525522
Ok(summary) => summary,
526523
Err(e) => {
@@ -635,30 +632,24 @@ impl<'a> SummariesCache<'a> {
635632
if *first_byte != CURRENT_CACHE_VERSION {
636633
failure::bail!("looks like a different Cargo's cache, bailing out");
637634
}
638-
let mut iter = memchr::Memchr::new(0, rest);
639-
let mut start = 0;
640-
if let Some(end) = iter.next() {
641-
let update = &rest[start..end];
635+
let mut iter = split(rest, 0);
636+
if let Some(update) = iter.next() {
642637
if update != last_index_update.as_bytes() {
643638
failure::bail!(
644639
"cache out of date: current index ({}) != cache ({})",
645640
last_index_update,
646641
str::from_utf8(update)?,
647642
)
648643
}
649-
start = end + 1;
650644
} else {
651645
failure::bail!("malformed file");
652646
}
653647
let mut ret = SummariesCache::default();
654-
while let Some(version_end) = iter.next() {
655-
let version = &rest[start..version_end];
648+
while let Some(version) = iter.next() {
656649
let version = str::from_utf8(version)?;
657650
let version = Version::parse(version)?;
658-
let summary_end = iter.next().unwrap();
659-
let summary = &rest[version_end + 1..summary_end];
651+
let summary = iter.next().unwrap();
660652
ret.versions.push((version, summary));
661-
start = summary_end + 1;
662653
}
663654
Ok(ret)
664655
}
@@ -740,3 +731,28 @@ impl IndexSummary {
740731
})
741732
}
742733
}
734+
735+
fn split<'a>(haystack: &'a [u8], needle: u8) -> impl Iterator<Item = &'a [u8]> + 'a {
736+
struct Split<'a> {
737+
haystack: &'a [u8],
738+
needle: u8,
739+
}
740+
741+
impl<'a> Iterator for Split<'a> {
742+
type Item = &'a [u8];
743+
744+
fn next(&mut self) -> Option<&'a [u8]> {
745+
if self.haystack.is_empty() {
746+
return None;
747+
}
748+
let (ret, remaining) = match memchr::memchr(self.needle, self.haystack) {
749+
Some(pos) => (&self.haystack[..pos], &self.haystack[pos + 1..]),
750+
None => (self.haystack, &[][..]),
751+
};
752+
self.haystack = remaining;
753+
Some(ret)
754+
}
755+
}
756+
757+
Split { haystack, needle }
758+
}

0 commit comments

Comments
 (0)