use std::borrow::Cow;
use crate::str::CowStrUtils;
use crate::{error, Error};
pub trait OptValidator {
type Error: Into<Error>;
fn check(&mut self, name: &str) -> Result<bool, Self::Error>;
fn split<'a>(&self, name: &Cow<'a, str>) -> Result<(Cow<'a, str>, Cow<'a, str>), Self::Error>;
}
pub trait PrefixedValidator {
type Error: Into<Error>;
fn reg_prefix(&mut self, val: &str) -> Result<(), Self::Error>;
fn unreg_prefix(&mut self, val: &str) -> Result<(), Self::Error>;
}
#[derive(Debug, Clone)]
pub struct PrefixOptValidator(Vec<String>);
#[cfg(target_os = "windows")]
impl Default for PrefixOptValidator {
fn default() -> Self {
Self::new(
["--/", "--", "-/", "-", "/"]
.map(|v| v.to_string())
.to_vec(),
)
}
}
#[cfg(not(target_os = "windows"))]
impl Default for PrefixOptValidator {
fn default() -> Self {
Self::new(["--/", "--", "-/", "-"].map(|v| v.to_string()).to_vec())
}
}
impl PrefixOptValidator {
pub fn new(prefix: Vec<String>) -> Self {
let mut _self = Self(prefix);
_self.sort_prefix();
_self
}
fn sort_prefix(&mut self) {
self.0.sort_by_key(|b| std::cmp::Reverse(b.len()));
}
pub fn add_prefix(&mut self, prefix: &str) -> &mut Self {
self.0.push(prefix.to_string());
self.sort_prefix();
self
}
}
impl OptValidator for PrefixOptValidator {
type Error = Error;
fn check(&mut self, name: &str) -> Result<bool, Self::Error> {
for prefix in self.0.iter() {
if name.starts_with(prefix) {
return Ok(true);
}
}
Ok(false)
}
fn split<'a>(&self, name: &Cow<'a, str>) -> Result<(Cow<'a, str>, Cow<'a, str>), Self::Error> {
for prefix in self.0.iter() {
if name.starts_with(prefix) {
return Ok(name.split_at(prefix.len()));
}
}
Err(error!(
"can not split the {}: invalid option name string",
name
))
}
}
impl PrefixedValidator for PrefixOptValidator {
type Error = Error;
fn reg_prefix(&mut self, val: &str) -> Result<(), Self::Error> {
if self.0.iter().any(|v| v == val) {
Err(error!("the prefix already exist"))
} else {
self.add_prefix(val);
Ok(())
}
}
fn unreg_prefix(&mut self, val: &str) -> Result<(), Self::Error> {
if let Some(index) = self.0.iter().position(|v| v == val) {
self.0.remove(index);
Ok(())
} else {
Err(error!("the prefix not exist"))
}
}
}