Skip to content

Instantly share code, notes, and snippets.

@JayKickliter
Created February 19, 2024 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JayKickliter/8a55de92dbf980c7fa996b72fe115f40 to your computer and use it in GitHub Desktop.
Save JayKickliter/8a55de92dbf980c7fa996b72fe115f40 to your computer and use it in GitHub Desktop.
Parsing a range of values in rust, suitable for command line clap parsing
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7d2fd8dc461ab1fc7216eb4e68c4517d
use std::str::FromStr;
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum ResOpt {
Fixed(u8),
Range(u8, u8),
}
impl FromStr for ResOpt {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<ResOpt, anyhow::Error> {
match s.split("..").collect::<Vec<&str>>().as_slice() {
// "res"
[res] => {
let res = u8::from_str(res)?;
Ok(ResOpt::Fixed(res))
}
// "Min.."
[min, ""] => {
let min = u8::from_str(min)?;
Ok(ResOpt::Range(min, 15))
}
// "..Max"
["", max] => {
let max = u8::from_str(max)?;
Ok(ResOpt::Range(0, max))
}
// "Min..Max"
[min, max] => {
let min = u8::from_str(min)?;
let max = u8::from_str(max)?;
Ok(ResOpt::Range(min, max))
}
_ => anyhow::bail!("{} is not a valid range", s),
}
}
}
fn main() {
assert_eq!(ResOpt::from_str("12").unwrap(), ResOpt::Fixed(12));
assert_eq!(ResOpt::from_str("9..").unwrap(), ResOpt::Range(9, 15));
assert_eq!(ResOpt::from_str("..12").unwrap(), ResOpt::Range(0, 12));
assert_eq!(ResOpt::from_str("9..12").unwrap(), ResOpt::Range(9, 12));
assert!(ResOpt::from_str("9.12").is_err(),);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment