mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-09 10:08:13 -07:00
45 lines
1.5 KiB
Rust
45 lines
1.5 KiB
Rust
use brk_error::{Error, Result};
|
|
use brk_rpc::Client;
|
|
use brk_types::{CheckedSub, Height};
|
|
|
|
pub struct Selector;
|
|
|
|
impl Selector {
|
|
pub fn parse(s: &str, client: &Client) -> Result<(Height, Height)> {
|
|
let (a, b) = s.split_once("..").unwrap_or((s, s));
|
|
let needs_tip = |p: &str| p == "tip" || p.starts_with("tip-");
|
|
let tip = if needs_tip(a) || needs_tip(b) {
|
|
Some(client.get_last_height()?)
|
|
} else {
|
|
None
|
|
};
|
|
let start = Self::endpoint(a, tip)?;
|
|
let end = Self::endpoint(b, tip)?;
|
|
if end < start {
|
|
return Err(Error::Parse(format!(
|
|
"range end {end} before start {start}"
|
|
)));
|
|
}
|
|
Ok((start, end))
|
|
}
|
|
|
|
fn endpoint(s: &str, tip: Option<Height>) -> Result<Height> {
|
|
if s == "tip" {
|
|
return Ok(tip.expect("tip pre-resolved when input contains 'tip'"));
|
|
}
|
|
if let Some(rest) = s.strip_prefix("tip-") {
|
|
let n: u32 = rest
|
|
.parse()
|
|
.map_err(|_| Error::Parse(format!("bad tip offset: {s}")))?;
|
|
let tip = tip.expect("tip pre-resolved when input contains 'tip'");
|
|
return tip
|
|
.checked_sub(n)
|
|
.ok_or_else(|| Error::Parse(format!("tip-{n} underflows genesis")));
|
|
}
|
|
let n: u32 = s
|
|
.parse()
|
|
.map_err(|_| Error::Parse(format!("bad height: {s}")))?;
|
|
Ok(Height::new(n))
|
|
}
|
|
}
|