1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
named!(get_arg, delimited!(tag!("\""), take_until!("\""), tag!("\"")));
named!(space_n_args, do_parse!(
multispace >>
arg: get_arg >>
(arg)
));
named!(get_args< Vec<&str> >, many0!( map_res!(space_n_args, str::from_utf8) ) );
use nom::IResult::Done;
use nom::{alphanumeric, multispace};
use std::str;
#[derive(Debug, Clone,Serialize,Deserialize)]
pub struct PackAction {
action: String,
args: Vec<String>
}
impl PackAction {
pub fn new(action: String) -> PackAction {
PackAction { action, args: Vec::new() }
}
pub fn add_arg(&mut self, new_arg: String) {
self.args.push(new_arg);
}
pub fn parse(from: &str) -> Result<PackAction, String> {
let (action, rest) = match alphanumeric(from.as_bytes()) {
Done(other, matched) => (matched, other),
_ => {return Err(format!("Failed to find action in {}", from)); },
};
let action_str = str::from_utf8(action).map_err(|e|e.to_string())?;
let args_str: Vec<String> = match get_args(rest) {
Done(_, matched) => {
matched.iter().map(|s|s.to_string()).collect()
},
_ => {return Err(format!("Failed to find args in {}", from)); },
};
Ok(PackAction { action: action_str.to_string(), args: args_str })
}
pub fn get_action(&self) -> &str {
&self.action
}
pub fn get_args(&self) -> &Vec<String> {
&self.args
}
}
#[test]
fn test_parse() {
let must_succeed = vec!["copy \"arg1\\spaced name\" \"$APP_DIR\\arg2\"", "apply", "modify \"arg1\"", "multiple \"arg1\" \"arg2\" \"arg3\" \"arg4\""];
for to_parse in must_succeed {
assert!(PackAction::parse(to_parse).is_ok());
}
}