///|
fn range_item_count(config : RomanRangeConfig) -> Result[Int, RomanRangeError] {
if config.max_items < 1 {
return Err(InvalidRangeItemLimit(config.max_items))
}
if config.step == 0 {
return Err(ZeroRangeStep)
}
if (config.start < config.end && config.step < 0) ||
(config.start > config.end && config.step > 0) {
return Err(RangeDirectionMismatch(config.start, config.end, config.step))
}
let distance = if config.end >= config.start {
config.end - config.start
} else {
config.start - config.end
}
let step_size = if config.step < 0 { -config.step } else { config.step }
let count = distance / step_size + 1
if count > config.max_items {
Err(RangeItemLimitExceeded(count, config.max_items))
} else {
Ok(count)
}
}
///|
/// Format an inclusive sequence after validating direction and output size.
pub fn format_roman_range(
config : RomanRangeConfig,
) -> Result[Array[RomanRangeEntry], RomanRangeError] {
let count = match range_item_count(config) {
Ok(value) => value
Err(error) => return Err(error)
}
let entries : Array[RomanRangeEntry] = []
let mut value = config.start
for index = 0; index < count; index = index + 1 {
let text = match format_with_config(value, config.format_config) {
Ok(formatted) => formatted
Err(error) => return Err(RangeValueFormatFailed(value, error))
}
entries.push({ value, text })
value = value + config.step
}
Ok(entries)
}