///|
fn parse_rule_number(text : String) -> Result[Int, RuleParseError] {
if text.length() == 0 {
return Err(RuleInvalidNumber(text))
}
if text.at(0).to_int() == 45 {
return Err(RuleParseNegativeCount)
}
let mut value = 0
let mut index = 0
while index < text.length() {
let code = text.at(index).to_int()
if code < 48 || code > 57 {
return Err(RuleInvalidNumber(text))
}
value = value * 10 + code - 48
index = index + 1
}
Ok(value)
}
///|
fn parse_single_rule(text : String) -> Result[DateRule, RuleParseError] {
let parts = [ for part in text.split(":") => part.to_owned() ]
if parts.length() != 2 {
return Err(RuleInvalidFormat)
}
let count = match parse_rule_number(parts[1]) {
Ok(value) => value
Err(error) => return Err(error)
}
match parts[0] {
"calendar-days" => Ok(CalendarDays(count))
"business-days" => Ok(BusinessDays(count))
"weeks" => Ok(Weeks(count))
"months" => Ok(Months(count))
"years" => Ok(Years(count))
unit => Err(RuleUnknownUnit(unit))
}
}
///|
/// Parse a stable comma-separated rule specification for library callers.
pub fn DateRule::parse(text : String) -> Result[DateRule, RuleParseError] {
if text.length() == 0 {
return Err(RuleInvalidFormat)
}
let parts = [ for part in text.split(",") => part.to_owned() ]
let rules = Array::new()
for part in parts {
if part.length() == 0 {
return Err(RuleInvalidFormat)
}
match parse_single_rule(part) {
Ok(rule) => rules.push(rule)
Err(error) => return Err(error)
}
}
if rules.length() == 1 {
Ok(rules[0])
} else {
Ok(Sequence(rules))
}
}