use clap::builder::{self, TypedValueParser};
use regex::Regex;
#[derive(Copy, Clone)]
pub struct Region
{
pub position: (i32, i32),
pub size: (i32, i32),
}
impl Region
{
pub const fn get_parser_formats() -> [&'static str; 1]
{
["{x},{y} {width}x{height}"]
}
}
impl builder::ValueParserFactory for Region
{
type Parser = RegionValueParser;
fn value_parser() -> Self::Parser
{
RegionValueParser
}
}
#[derive(Clone)]
pub struct RegionValueParser;
impl TypedValueParser for RegionValueParser
{
type Value = Region;
fn parse_ref(
&self,
_command: &clap::Command,
_argument: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error>
{
if value.is_empty()
{
return Err(clap::Error::raw(
clap::ErrorKind::EmptyValue,
"The region argument must not be empty.",
));
}
let value = value.to_str().ok_or_else(|| {
clap::Error::raw(
clap::ErrorKind::InvalidUtf8,
"The argument containted invalid UTF-8 characters.",
)
})?;
let regex = Regex::new(r"(-?\d+),(-?\d+) (\d+)x(\d+)").unwrap();
let captures = regex.captures(value).ok_or_else(|| {
clap::Error::raw(
clap::ErrorKind::ValueValidation,
"The argument was malformed. Please use the format: '{x},{y} {width}x{height}'.",
)
})?;
let position = (
captures.get(1).unwrap().as_str().parse::<i32>().unwrap(),
captures.get(2).unwrap().as_str().parse::<i32>().unwrap(),
);
let size = (
captures.get(3).unwrap().as_str().parse::<i32>().unwrap(),
captures.get(4).unwrap().as_str().parse::<i32>().unwrap(),
);
Ok(Region { position, size })
}
}