use std::collections::HashMap;
#[derive(Clone)]
pub enum Variant {
Plain(fn(&Handler)),
WithArg(fn(&Handler, String)),
}
#[derive(Clone)]
pub enum ArgType {
Flag(bool),
Content(String),
}
#[derive(Clone)]
pub struct Handler {
actions: Option<HashMap<String, Variant>>,
hints: Option<HashMap<String, String>>,
values: Option<HashMap<String, ArgType>>,
}
impl Handler {
pub fn new() -> Handler {
Handler {
actions: None,
hints: None,
values: None,
}
}
pub fn parse_args(&mut self, args: Vec<String>) -> Result<(), String> {
if let Some(map) = &self.actions {
if let None = &mut self.values {
let mut new_values: HashMap<String, ArgType> = HashMap::new();
let mut option_key: Option<String> = None;
let mut status: Result<(), String> = Ok(());
let args = args.iter().skip(1);
for option in args {
match map.get(option) {
None => {
if let Some(key) = &option_key {
new_values
.insert(key.clone(), ArgType::Content(option.to_string()));
status = Ok(());
} else {
let mut msg = String::from("error parsing argument : ");
msg.push_str(&option.as_str());
return Err(msg);
}
}
Some(variant) => {
match variant {
Variant::Plain(_) => {
new_values.insert(option.to_string(), ArgType::Flag(true));
}
Variant::WithArg(_) => {
let mut msg = String::from("handler does not have value : ");
msg.push_str(&option.as_str());
status = Err(msg);
option_key = Some(option.to_string());
}
}
}
}
}
if new_values.len() > 0 {
self.values = Some(new_values);
}
status
} else {
return Err(String::from("handler values not empty"));
}
} else {
Err(String::from("no action handlers found"))
}
}
pub fn get_arg(&self, key: &str) -> Option<ArgType> {
match &self.values {
None => None,
Some(value_map) => {
if let Some(argtype) = value_map.get(key) {
return Some(argtype.clone());
} else {
return None;
}
}
}
}
pub fn get_actions(&self) -> Option<&HashMap<String, Variant>> {
if let Some(map) = &self.actions {
return Some(map);
} else {
return None;
}
}
pub fn clone_actions(&self) -> Option<HashMap<String, Variant>> {
if let Some(map) = &self.actions {
return Some((*map).clone());
} else {
return None;
}
}
pub fn extract_actions(self) -> Option<HashMap<String, Variant>> {
if let Some(map) = self.actions {
return Some(map);
} else {
return None;
}
}
pub fn get_hints(&self) -> Option<&HashMap<String, String>> {
if let Some(map) = &self.hints {
return Some(map);
} else {
return None;
}
}
pub fn clone_hints(&self) -> Option<HashMap<String, String>> {
if let Some(map) = &self.hints {
return Some((*map).clone());
} else {
return None;
}
}
pub fn extract_hints(self) -> Option<HashMap<String, String>> {
if let Some(map) = self.hints {
return Some(map);
} else {
return None;
}
}
pub fn add(&mut self, parameter: String, action: Variant, hint: String) {
match &mut self.actions {
None => {
let mut map: HashMap<String, Variant> = HashMap::new();
map.insert(parameter.clone(), action);
self.actions = Some(map);
}
Some(map) => {
map.insert(parameter.clone(), action);
}
}
match &mut self.hints {
None => {
let mut map: HashMap<String, String> = HashMap::new();
map.insert(parameter, hint);
self.hints = Some(map);
}
Some(map) => {
map.insert(parameter, hint);
}
}
}
pub fn append(&mut self, handler: Handler) {
if let Some(target_actions) = handler.clone_actions() {
if let Some(current_actions) = &mut self.actions {
current_actions.extend(target_actions);
}
}
if let Some(target_hints) = handler.extract_hints() {
if let Some(current_hints) = &mut self.hints {
current_hints.extend(target_hints);
}
}
}
}