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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
use vec_shift::Shift;
use std::str::FromStr;
use std::error::Error as StdError;
use utils::parse_quotes;
/// Defines how an operation on an `Args` method failed.
#[derive(Debug)]
pub enum Error {
/// "END-OF-STRING", more precisely, there isn't anything to parse anymore.
Eos,
/// A parsing operation failed; the error in it can be of any returned from the `FromStr` trait.
Parse(Box<StdError>),
}
type Result<T> = ::std::result::Result<T, Error>;
#[derive(Debug, Clone)]
pub struct Args {
delimiter: String,
delimiter_split: Vec<String>,
}
impl Args {
pub fn new(message: &str, delimiter: &str) -> Self {
Args {
delimiter: delimiter.to_string(),
delimiter_split: message.split(delimiter).map(|s| s.to_string()).collect(),
}
}
/// Removes the first element, parses it to a specific type if necessary, returns.
pub fn single<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
if self.delimiter_split.is_empty() {
return Err(Error::Eos);
}
self.delimiter_split.shift()
.ok_or(Error::Eos)?
.parse::<T>()
.map_err(|e| Error::Parse(Box::new(e)))
}
/// Like [`single`], but doesn't remove the element.
///
/// [`single`]: #method.single
pub fn single_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
if self.delimiter_split.is_empty() {
return Err(Error::Eos);
}
self.delimiter_split.get(0)
.ok_or(Error::Eos)?
.parse::<T>()
.map_err(|e| Error::Parse(Box::new(e)))
}
/// Skips if there's a first element, but also returns it.
pub fn skip(&mut self) -> Option<String> {
self.delimiter_split.shift()
}
/// Like [`skip`], but allows for multiple at once.
///
/// [`skip`]: #method.skip
pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> {
let mut vec = Vec::with_capacity(i as usize);
for _ in 0..i {
vec.push(match self.delimiter_split.shift() {
Some(x) => x,
None => return None,
});
}
Some(vec)
}
/// Like [`single`], but takes quotes into account.
///
/// [`single`]: #method.single
pub fn single_quoted<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
}
/// Like [`single_quoted`], but doesn't remove the element.
///
/// [`single_quoted`]: #method.single_quoted
pub fn single_quoted_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
}
/// Like [`list`], but takes quotes into account.
///
/// [`list`]: #method.list
pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>> where T::Err: StdError + 'static {
if self.delimiter_split.is_empty() {
return Err(Error::Eos);
}
parse_quotes(&self.delimiter_split.join(&self.delimiter)).into_iter().map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))).collect()
}
/// Empty outs the internal vector while parsing (if necessary) and returning them
pub fn list<T: FromStr>(self) -> Result<Vec<T>> where T::Err: StdError + 'static {
if self.delimiter_split.is_empty() {
return Err(Error::Eos);
}
self.delimiter_split.into_iter().map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))).collect()
}
/// This method is just `internal_vector.join(delimiter)`
pub fn full(&self) -> String {
self.delimiter_split.join(&self.delimiter)
}
}
impl ::std::ops::Deref for Args {
type Target = [String];
fn deref(&self) -> &Self::Target {
&self.delimiter_split
}
}
|