Guest User

Untitled

a guest
Apr 25th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.53 KB | None | 0 0
  1. use std::collections::{BTreeMap, HashSet};
  2. use std::str::FromStr;
  3. use std::fmt::Debug;
  4. use std::cell::{RefCell};
  5.  
  6.  
  7. pub trait PosArgBase {
  8. fn name(&self) -> &str;
  9. fn desc(&self) -> &str;
  10. fn found(&self) -> bool;
  11. fn parse(&mut self, s: &str);
  12. }
  13.  
  14. pub struct PosArg<T> where T: FromStr, <T as FromStr>::Err: Debug {
  15. name: String,
  16. desc: String,
  17. val: Option<T>,
  18. }
  19.  
  20. impl<T> PosArg<T>
  21. where T: FromStr,
  22. <T as FromStr>::Err: Debug {
  23.  
  24. pub fn new(name: String, desc: String) -> Self {
  25. Self{name, desc, val: None}
  26. }
  27.  
  28. pub fn val(&mut self) -> Option<T> { self.val.take() }
  29. }
  30.  
  31. impl<T> PosArgBase for PosArg<T>
  32. where T: FromStr,
  33. <T as FromStr>::Err: Debug {
  34.  
  35. fn name(&self) -> &str { &self.name }
  36. fn desc(&self) -> &str { &self.desc }
  37. fn found(&self) -> bool { self.val.is_some() }
  38.  
  39. fn parse(&mut self, s: &str) {
  40. self.val = T::from_str(s).ok();
  41. }
  42. }
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49. pub trait KVArgBase {
  50. fn name(&self) -> &str;
  51. fn desc(&self) -> &str;
  52. fn short_key(&self) -> Option<char>; // Not valid for positional argument
  53. fn found(&self) -> bool;
  54.  
  55. fn parse(&mut self, s: &str);
  56. }
  57.  
  58. pub struct KVArg<T>
  59. where T: FromStr,
  60. <T as FromStr>::Err: Debug {
  61. name: String,
  62. desc: String,
  63. short_key: Option<char>,
  64. val: Option<T>,
  65. }
  66.  
  67. impl<T> KVArg<T>
  68. where T: FromStr,
  69. <T as FromStr>::Err: Debug {
  70.  
  71. pub fn new(name: String, short_key: Option<char>, desc: String) -> RefCell<Self> {
  72. RefCell::new(Self{name, desc, val: None, short_key})
  73. }
  74.  
  75. pub fn val(self) -> Option<T> { self.val }
  76. }
  77.  
  78.  
  79. impl<T> KVArgBase for KVArg<T> where T: FromStr, <T as FromStr>::Err: Debug {
  80. fn name(&self) -> &str { &self.name }
  81. fn desc(&self) -> &str { &self.desc }
  82. fn short_key(&self) -> Option<char> { self.short_key }
  83. fn found(&self) -> bool { self.val.is_some() }
  84.  
  85. fn parse(&mut self, s: &str) {
  86. self.val = T::from_str(s).ok();
  87. }
  88.  
  89. }
  90.  
  91.  
  92.  
  93.  
  94.  
  95. pub trait FlagArgBase {
  96. fn name(&self) -> &str;
  97. fn desc(&self) -> &str;
  98. fn short_key(&self) -> Option<char>; // Not valid for positional argument
  99. fn found(&self) -> bool;
  100.  
  101. fn parse(&mut self);
  102. }
  103.  
  104.  
  105. pub struct FlagArg {
  106. name: String,
  107. desc: String,
  108. short_key: Option<char>,
  109. val: bool,
  110. }
  111.  
  112. impl FlagArg {
  113. pub fn new(name: String, desc: String, short_key: Option<char>) -> RefCell<Self> {
  114. RefCell::new(Self{name, desc, short_key, val: false})
  115. }
  116. }
  117.  
  118. impl FlagArgBase for FlagArg {
  119. fn name(&self) -> &str { &self.name }
  120. fn desc(&self) -> &str { &self.desc }
  121. fn short_key(&self) -> Option<char> { self.short_key }
  122. fn found(&self) -> bool { self.val }
  123.  
  124. fn parse(&mut self) { self.val = true; }
  125. }
  126.  
  127.  
  128.  
  129.  
  130.  
  131. pub struct Parser<'a> {
  132. pos_args: Vec<&'a mut PosArgBase>,
  133. pos_arg_names: HashSet<String>,
  134.  
  135. kv_keys: BTreeMap<String, &'a RefCell<KVArgBase>>,
  136.  
  137. flag_keys: BTreeMap<String, &'a RefCell<FlagArgBase>>,
  138. }
  139.  
  140. impl<'a> Parser<'a> {
  141. pub fn new() -> Self {
  142. Self{
  143. pos_args: Vec::new(),
  144. pos_arg_names: HashSet::new(),
  145. kv_keys: BTreeMap::new(),
  146. flag_keys: BTreeMap::new(),
  147. }
  148. }
  149.  
  150.  
  151. pub fn add_pos_arg(&mut self, pos_arg: &'a mut PosArgBase) {
  152. assert!(!self.pos_arg_names.contains(pos_arg.name()));
  153. self.pos_arg_names.insert(String::from(pos_arg.name()));
  154. self.pos_args.push(pos_arg);
  155. }
  156.  
  157. pub fn add_kv_arg(&mut self, kv_arg: &'a RefCell<KVArgBase>) {
  158.  
  159. assert!(!self.kv_keys.contains_key(kv_arg.borrow().name())
  160. && !self.flag_keys.contains_key(kv_arg.borrow().name()));
  161. assert!(kv_arg.borrow().name().len() > 1);
  162.  
  163. self.kv_keys.insert(String::from(kv_arg.borrow().name()), kv_arg);
  164.  
  165. let short_key = kv_arg.borrow().short_key();
  166. if let Some(c) = short_key {
  167. let cs = c.to_string();
  168. assert!(!self.kv_keys.contains_key(&cs)
  169. && !self.flag_keys.contains_key(&cs));
  170. self.kv_keys.insert(cs, kv_arg);
  171. };
  172. }
  173.  
  174. pub fn add_flag_arg(&mut self, flag_arg: &'a RefCell<FlagArgBase>) {
  175. assert!(!self.flag_keys.contains_key(flag_arg.borrow().name())
  176. && !self.kv_keys.contains_key(flag_arg.borrow().name()));
  177. assert!(flag_arg.borrow().name().len() > 1);
  178.  
  179. self.flag_keys.insert(String::from(flag_arg.borrow().name()), flag_arg);
  180.  
  181. let short_key = flag_arg.borrow().short_key();
  182. if let Some(c) = short_key {
  183. let cs = c.to_string();
  184. assert!(!self.flag_keys.contains_key(&cs)
  185. && !self.kv_keys.contains_key(&cs));
  186. self.flag_keys.insert(cs, flag_arg);
  187. };
  188. }
  189.  
  190. pub fn parse(&mut self) {
  191. self.parse_vec(std::env::args().collect());
  192. }
  193.  
  194. pub fn parse_vec(&mut self, argv: Vec<String>) {
  195.  
  196. let mut pos_args_consumed = 0;
  197.  
  198. let mut it = argv.iter();
  199. it.next(); // skip first arg (program path)
  200. while let Some(arg) = it.next() {
  201. let mut chars = arg.chars();
  202. let first = chars.next().unwrap();
  203. let second = chars.next().unwrap();
  204.  
  205. if first == '-' {
  206. // Long key kv arg
  207. let key = if second == '-' {
  208. String::from(&arg[2..])
  209. } else {
  210. String::from(&arg[1..])
  211. };
  212.  
  213. if let Some(arg_rc) = self.kv_keys.get(&key) {
  214. assert!(!arg_rc.borrow().found());
  215. // let mut q:() = arg_rc;
  216. arg_rc.borrow_mut().parse(it.next().unwrap());
  217. } else if let Some(arg_rc) = self.flag_keys.get(&key) {
  218. assert!(!arg_rc.borrow().found());
  219. arg_rc.borrow_mut().parse();
  220. } else {
  221. panic!("No such key `{:?}`", key);
  222. }
  223.  
  224. } else {
  225. // Positional arg
  226. if pos_args_consumed >= self.pos_args.len() {
  227. panic!("Too many positional args!");
  228. }
  229.  
  230. self.pos_args[pos_args_consumed].parse(arg);
  231. pos_args_consumed += 1;
  232. }
  233. }
  234. }
  235.  
  236.  
  237.  
  238. }
  239.  
  240.  
  241.  
  242.  
  243. #[cfg(test)]
  244. mod tests {
  245. use super::*;
  246.  
  247. #[test]
  248. fn it_works() {
  249. let kv = KVArg::<i32>::new("first".to_string(), Some('f'), "first argument".to_string());
  250. let mut parser = Parser::new();
  251. parser.add_kv_arg(&kv);
  252.  
  253. let args = vec!["".to_string(), "-f".to_string(), "42".to_string()];
  254.  
  255. parser.parse_vec(args);
  256.  
  257. assert!(kv.borrow_mut().val().unwrap() == 42);
  258. }
  259. }
Add Comment
Please, Sign In to add comment