1 use crate::api
::schema
::*;
10 Argument { value: String }
,
11 Option { name: String, value: Option<String> }
,
14 fn parse_argument(arg
: &str) -> RawArgument
{
15 let bytes
= arg
.as_bytes();
17 let length
= bytes
.len();
19 if length
< 2 || bytes
[0] != b'
-'
{
20 return RawArgument
::Argument
{
21 value
: arg
.to_string(),
29 return RawArgument
::Separator
;
34 for start
in first
..length
{
35 if bytes
[start
] == b'
='
{
36 // Since we take a &str, we know the contents of it are valid utf8.
37 // Since bytes[start] == b'=', we know the byte beginning at start is a single-byte
38 // code pointer. We also know that 'first' points exactly after a single-byte code
39 // point as it points to the first byte after a hyphen.
40 // Therefore we know arg[first..start] is valid utf-8, therefore it is safe to use
41 // get_unchecked() to speed things up.
42 return RawArgument
::Option
{
43 name
: unsafe { arg.get_unchecked(first..start).to_string() }
,
44 value
: Some(unsafe { arg.get_unchecked((start + 1)..).to_string() }
),
49 return RawArgument
::Option
{
50 name
: unsafe { arg.get_unchecked(first..).to_string() }
,
55 pub fn parse_arguments
<T
: AsRef
<str>>(
57 arg_param
: &Vec
<&'
static str>,
58 schema
: &ObjectSchema
,
59 ) -> Result
<(Value
,Vec
<String
>), ParameterError
> {
61 let mut errors
= ParameterError
::new();
63 let properties
= &schema
.properties
;
65 let mut data
: Vec
<(String
, String
)> = vec
![];
66 let mut rest
: Vec
<String
> = vec
![];
70 while pos
< args
.len() {
71 match parse_argument(args
[pos
].as_ref()) {
72 RawArgument
::Separator
=> {
75 RawArgument
::Option { name, value }
=> {
78 let mut want_bool
= false;
79 let mut can_default
= false;
80 if let Some((_optional
, param_schema
)) = properties
.get
::<str>(&name
) {
81 if let Schema
::Boolean(boolean_schema
) = param_schema
.as_ref() {
83 if let Some(default) = boolean_schema
.default {
84 if default == false { can_default = true; }
91 let mut next_is_argument
= false;
92 let mut next_is_bool
= false;
94 if (pos
+ 1) < args
.len() {
95 let next
= args
[pos
+1].as_ref();
96 if let RawArgument
::Argument { value: _}
= parse_argument(next
) {
97 next_is_argument
= true;
98 if let Ok(_
) = parse_boolean(next
) { next_is_bool = true; }
105 data
.push((name
, args
[pos
].as_ref().to_string()));
106 } else if can_default
{
107 data
.push((name
, "true".to_string()));
109 errors
.push(format_err
!("parameter '{}': {}", name
,
110 "missing boolean value."));
115 if next_is_argument
{
117 data
.push((name
, args
[pos
].as_ref().to_string()));
119 errors
.push(format_err
!("parameter '{}': {}", name
,
120 "missing parameter value."));
125 data
.push((name
, v
));
129 RawArgument
::Argument { value }
=> {
137 rest
.reserve(args
.len() - pos
);
138 for i
in &args
[pos
..] {
139 rest
.push(i
.as_ref().to_string());
142 for i
in 0..arg_param
.len() {
144 data
.push((arg_param
[i
].to_string(), rest
[i
].clone()));
146 errors
.push(format_err
!("missing argument '{}'", arg_param
[i
]));
150 if errors
.len() > 0 { return Err(errors); }
152 if arg_param
.len() > 0 {
153 rest
= rest
[arg_param
.len()..].to_vec();
156 let options
= parse_parameter_strings(&data
, schema
, true)?
;
163 fn test_boolean_arg() {
165 let schema
= ObjectSchema
::new("Parameters:")
167 "enable", BooleanSchema
::new("Enable")
170 let mut variants
: Vec
<(Vec
<&str>, bool
)> = vec
![];
171 variants
.push((vec
!["-enable"], true));
172 variants
.push((vec
!["-enable=1"], true));
173 variants
.push((vec
!["-enable", "yes"], true));
174 variants
.push((vec
!["-enable", "Yes"], true));
175 variants
.push((vec
!["--enable", "1"], true));
176 variants
.push((vec
!["--enable", "ON"], true));
177 variants
.push((vec
!["--enable", "true"], true));
179 variants
.push((vec
!["--enable", "0"], false));
180 variants
.push((vec
!["--enable", "no"], false));
181 variants
.push((vec
!["--enable", "off"], false));
182 variants
.push((vec
!["--enable", "false"], false));
184 for (args
, expect
) in variants
{
185 let res
= parse_arguments(&args
, &vec
![], &schema
);
186 assert
!(res
.is_ok());
187 if let Ok((options
, rest
)) = res
{
188 assert
!(options
["enable"] == expect
);
189 assert
!(rest
.len() == 0);
195 fn test_argument_paramenter() {
197 let schema
= ObjectSchema
::new("Parameters:")
198 .required("enable", BooleanSchema
::new("Enable."))
199 .required("storage", StringSchema
::new("Storage."));
201 let args
= vec
!["-enable", "local"];
202 let res
= parse_arguments(&args
, &vec
!["storage"], &schema
);
203 assert
!(res
.is_ok());
204 if let Ok((options
, rest
)) = res
{
205 assert
!(options
["enable"] == true);
206 assert
!(options
["storage"] == "local");
207 assert
!(rest
.len() == 0);