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`.
This commit is contained in:
+19
-24
@@ -394,12 +394,9 @@ fn parse_name<T: Pep508Url>(cursor: &mut Cursor) -> Result<PackageName, Pep508Er
|
||||
// https://peps.python.org/pep-0508/#names
|
||||
// ^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$ with re.IGNORECASE
|
||||
let start = cursor.pos();
|
||||
let mut name = String::new();
|
||||
|
||||
if let Some((index, char)) = cursor.next() {
|
||||
if matches!(char, 'A'..='Z' | 'a'..='z' | '0'..='9') {
|
||||
name.push(char);
|
||||
} else {
|
||||
if !matches!(char, 'A'..='Z' | 'a'..='z' | '0'..='9') {
|
||||
// Check if the user added a filesystem path without a package name. pip supports this
|
||||
// in `requirements.txt`, but it doesn't adhere to the PEP 508 grammar.
|
||||
let mut clone = cursor.clone().at(start);
|
||||
@@ -431,26 +428,24 @@ fn parse_name<T: Pep508Url>(cursor: &mut Cursor) -> Result<PackageName, Pep508Er
|
||||
}
|
||||
|
||||
loop {
|
||||
match cursor.peek() {
|
||||
Some((index, char @ ('A'..='Z' | 'a'..='z' | '0'..='9' | '.' | '-' | '_'))) => {
|
||||
name.push(char);
|
||||
cursor.next();
|
||||
// [.-_] can't be the final character
|
||||
if cursor.peek().is_none() && matches!(char, '.' | '-' | '_') {
|
||||
return Err(Pep508Error {
|
||||
message: Pep508ErrorSource::String(format!(
|
||||
"Package name must end with an alphanumeric character, not '{char}'"
|
||||
)),
|
||||
start: index,
|
||||
len: char.len_utf8(),
|
||||
input: cursor.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Some(_) | None => {
|
||||
return Ok(PackageName::new(name)
|
||||
.expect("`PackageName` validation should match PEP 508 parsing"));
|
||||
if let Some((index, char @ ('A'..='Z' | 'a'..='z' | '0'..='9' | '.' | '-' | '_'))) =
|
||||
cursor.peek()
|
||||
{
|
||||
cursor.next();
|
||||
// [.-_] can't be the final character
|
||||
if cursor.peek().is_none() && matches!(char, '.' | '-' | '_') {
|
||||
return Err(Pep508Error {
|
||||
message: Pep508ErrorSource::String(format!(
|
||||
"Package name must end with an alphanumeric character, not `{char}`"
|
||||
)),
|
||||
start: index,
|
||||
len: char.len_utf8(),
|
||||
input: cursor.to_string(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let len = cursor.pos() - start;
|
||||
return Ok(PackageName::from_str(cursor.slice(start, len)).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1033,7 +1028,7 @@ mod tests {
|
||||
assert_snapshot!(
|
||||
parse_pep508_err("name_"),
|
||||
@"
|
||||
Package name must end with an alphanumeric character, not '_'
|
||||
Package name must end with an alphanumeric character, not `_`
|
||||
name_
|
||||
^"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user