use anyhow::{Context, Result};
#[derive(Debug)]
pub struct LedgerRange {
pub start: u32,
pub end: u32,
}
impl LedgerRange {
pub fn parse(input: &str, latest_ledger: Option<u32>) -> Result<Self> {
if input.trim().starts_with('-') {
let latest = latest_ledger.ok_or_else(|| anyhow::anyhow!("Could not determine latest ledger"))?;
let count = input.trim()[1..].parse::<u32>()
.context("Invalid negative ledger count")?;
if count == 0 {
anyhow::bail!("Ledger count must be greater than 0");
}
if count > latest {
anyhow::bail!("Cannot query {} ledgers from latest ({}), exceeds available ledgers", count, latest);
}
let start = latest - count + 1;
let end = latest;
return Ok(LedgerRange { start, end });
}
if let Some((start_str, end_str)) = input.split_once('-') {
let start = start_str.trim().parse::<u32>()
.context("Invalid start ledger number")?;
let end = end_str.trim().parse::<u32>()
.context("Invalid end ledger number")?;
if start > end {
anyhow::bail!("Start ledger must be less than or equal to end ledger");
}
Ok(LedgerRange { start, end })
} else {
let ledger = input.trim().parse::<u32>()
.context("Invalid ledger number")?;
Ok(LedgerRange { start: ledger, end: ledger })
}
}
pub fn iter(&self) -> impl Iterator<Item = u32> {
self.start..=self.end
}
pub fn is_range(&self) -> bool {
self.start != self.end
}
}