Skip to content

Commit 7a21b71

Browse files
Avoid allocating for names in the PEP 508 parser (#10476)
## Summary We can read from the slice directly. I don't think this will affect performance today, because `from_str` will then allocate, but it _should_ be a speedup once #10475 merges, since we can then avoid allocating a `String` and go straight from `str` to `ArcStr`.
1 parent d44affa commit 7a21b71

File tree

1 file changed

+19
-24
lines changed

1 file changed

+19
-24
lines changed

crates/uv-pep508/src/lib.rs

+19-24
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,9 @@ fn parse_name<T: Pep508Url>(cursor: &mut Cursor) -> Result<PackageName, Pep508Er
394394
// https://peps.python.org/pep-0508/#names
395395
// ^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$ with re.IGNORECASE
396396
let start = cursor.pos();
397-
let mut name = String::new();
398397

399398
if let Some((index, char)) = cursor.next() {
400-
if matches!(char, 'A'..='Z' | 'a'..='z' | '0'..='9') {
401-
name.push(char);
402-
} else {
399+
if !matches!(char, 'A'..='Z' | 'a'..='z' | '0'..='9') {
403400
// Check if the user added a filesystem path without a package name. pip supports this
404401
// in `requirements.txt`, but it doesn't adhere to the PEP 508 grammar.
405402
let mut clone = cursor.clone().at(start);
@@ -431,26 +428,24 @@ fn parse_name<T: Pep508Url>(cursor: &mut Cursor) -> Result<PackageName, Pep508Er
431428
}
432429

433430
loop {
434-
match cursor.peek() {
435-
Some((index, char @ ('A'..='Z' | 'a'..='z' | '0'..='9' | '.' | '-' | '_'))) => {
436-
name.push(char);
437-
cursor.next();
438-
// [.-_] can't be the final character
439-
if cursor.peek().is_none() && matches!(char, '.' | '-' | '_') {
440-
return Err(Pep508Error {
441-
message: Pep508ErrorSource::String(format!(
442-
"Package name must end with an alphanumeric character, not '{char}'"
443-
)),
444-
start: index,
445-
len: char.len_utf8(),
446-
input: cursor.to_string(),
447-
});
448-
}
449-
}
450-
Some(_) | None => {
451-
return Ok(PackageName::new(name)
452-
.expect("`PackageName` validation should match PEP 508 parsing"));
431+
if let Some((index, char @ ('A'..='Z' | 'a'..='z' | '0'..='9' | '.' | '-' | '_'))) =
432+
cursor.peek()
433+
{
434+
cursor.next();
435+
// [.-_] can't be the final character
436+
if cursor.peek().is_none() && matches!(char, '.' | '-' | '_') {
437+
return Err(Pep508Error {
438+
message: Pep508ErrorSource::String(format!(
439+
"Package name must end with an alphanumeric character, not `{char}`"
440+
)),
441+
start: index,
442+
len: char.len_utf8(),
443+
input: cursor.to_string(),
444+
});
453445
}
446+
} else {
447+
let len = cursor.pos() - start;
448+
return Ok(PackageName::from_str(cursor.slice(start, len)).unwrap());
454449
}
455450
}
456451
}
@@ -1033,7 +1028,7 @@ mod tests {
10331028
assert_snapshot!(
10341029
parse_pep508_err("name_"),
10351030
@"
1036-
Package name must end with an alphanumeric character, not '_'
1031+
Package name must end with an alphanumeric character, not `_`
10371032
name_
10381033
^"
10391034
);

0 commit comments

Comments
 (0)