in util/label/label.rs [105:178]
fn consume_package_name<'s>(input: &'s str, label: &'s str) -> Result<(&'s str, Option<&'s str>)> {
let is_absolute = match input.rfind("//") {
None => false,
Some(0) => true,
Some(_) => {
return Err(LabelError(err(
label,
"'//' cannot appear in the middle of the label.",
)));
}
};
let (package_name, rest) = match (is_absolute, input.find(':')) {
(false, colon_pos) if colon_pos.map_or(true, |pos| pos != 0) => {
return Err(LabelError(err(
label,
"relative packages are not permitted.",
)));
}
(_, colon_pos) => {
let (input, colon_pos) = if is_absolute {
(&input[2..], colon_pos.map(|cp| cp - 2))
} else {
(input, colon_pos)
};
match colon_pos {
Some(colon_pos) => (&input[0..colon_pos], &input[colon_pos..]),
None => (input, ""),
}
}
};
if package_name.is_empty() {
return Ok((rest, None));
}
if !package_name.chars().all(|c| {
c.is_ascii_alphanumeric()
|| c == '/'
|| c == '-'
|| c == '.'
|| c == ' '
|| c == '$'
|| c == '('
|| c == ')'
|| c == '_'
}) {
return Err(LabelError(err(
label,
"package names may contain only A-Z, \
a-z, 0-9, '/', '-', '.', ' ', '$', '(', ')' and '_'.",
)));
}
if package_name.ends_with('/') {
return Err(LabelError(err(
label,
"package names may not end with '/'.",
)));
}
if rest.is_empty() && is_absolute {
// This label doesn't contain the target name, we have to use
// last segment of the package name as target name.
return Ok((
match package_name.rfind('/') {
Some(pos) => &package_name[pos..],
None => package_name,
},
Some(package_name),
));
}
Ok((rest, Some(package_name)))
}