///|
/// Parse `positive-weight: A > B` or `positive-weight:` for abstention.
pub fn parse_ballot(input : String) -> Result[Ballot, Diagnostic] {
if input.length() > 4096 {
return Err(problem("line.limit", "at most 4096 code units"))
}
let parts = input.split(":").to_array()
if parts.length() != 2 {
return Err(problem("ballot.syntax", "expected weight: ranking"))
}
let number = parts[0].trim().to_owned()
if number.is_empty() {
return Err(problem("weight.syntax", "missing decimal weight"))
}
let mut weight = 0
for ch in number {
if ch < '0' || ch > '9' {
return Err(problem("weight.syntax", "decimal digits only"))
}
let digit = ch.to_int() - 48
if weight > (1000000 - digit) / 10 {
return Err(problem("weight.range", "expected 1..1000000"))
}
weight = weight * 10 + digit
}
let tail = parts[1].trim().to_owned()
let ranking : Array[String] = []
if !tail.is_empty() {
for item in tail.split(">") {
let id = item.trim().to_owned()
if id.is_empty() {
return Err(
problem("ranking.empty", "missing candidate between separators"),
)
}
ranking.push(id)
}
}
Ballot::new(ranking, weight)
}