From 845901f41d559c07b1adf8000041c44449a41854 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 16 Nov 2018 13:14:11 +0100 Subject: [PATCH] implement getopt parser - first try --- src/getopts.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 14 +++++++ 3 files changed, 124 insertions(+) create mode 100644 src/getopts.rs diff --git a/src/getopts.rs b/src/getopts.rs new file mode 100644 index 00000000..4fd8be20 --- /dev/null +++ b/src/getopts.rs @@ -0,0 +1,109 @@ +use crate::api::schema::*; + +use failure::*; +use serde_json::{json, Value}; + +#[derive(Debug)] +enum RawArgument { + Separator, + Argument { value: String }, + Option { name: String, value: Option }, +} + +fn parse_argument(arg: &str) -> RawArgument { + + let chars: Vec = arg.chars().collect(); + + let length = chars.len(); + + if length >= 2 && chars[0] == '-' && chars[1] == '-' { + + if length == 2 { return RawArgument::Separator; } + + for start in 2..length { + if chars[start] == '=' { + let name: String = chars[2..start].iter().collect(); + let value: String = chars[start+1..length].iter().collect(); + return RawArgument::Option { name, value: Some(value) } + } + } + + let name: String = chars[2..].iter().collect(); + return RawArgument::Option { name: name, value: None } + + } + + RawArgument::Argument { value: arg.to_string() } +} + +pub fn parse_arguments(args: &Vec, schema: &Schema) -> Value { + + println!("ARGS {:?}", args); + + let properties = match schema { + Schema::Object(ObjectSchema { properties, .. }) => properties, + _ => panic!("Expected Object Schema."), + }; + + let mut data: Vec<(String, String)> = vec![]; + let mut rest: Vec = vec![]; + + let mut pos = 0; + + let mut skip = false; + + loop { + if skip { + rest.push(args[pos].clone()); + } else { + match parse_argument(&args[pos]) { + RawArgument::Separator => { + skip = true; + } + RawArgument::Option { name, value } => { + match value { + None => { + if pos < args.len() { + if let RawArgument::Argument { value: next } = parse_argument(&args[pos+1]) { + pos += 1; + data.push((name, next)); + } else { + if let Some(Schema::Boolean(jss_boolean)) = properties.get::(&name) { + if let Some(default) = jss_boolean.default { + if default == false { + data.push((name, "true".to_string())); + } else { + panic!("negative Bool requires argument"); + } + } else { + data.push((name, "true".to_string())); + } + } + } + } + } + Some(v) => { + data.push((name, v)); + } + } + } + RawArgument::Argument { value } => { + rest.push(value); + } + } + } + + pos += 1; + if pos >= args.len() { break; } + } + + println!("Options {:?}", data); + println!("REST {:?}", rest); + + match parse_parameter_strings(&data, schema, true) { + Ok(value) => value, + Err(perror) => { + panic!(format!("{:?}", perror)); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index b739a89a..a547fba9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub mod api { } +pub mod getopts; pub mod api3; diff --git a/src/main.rs b/src/main.rs index 140bb2ab..d264ed5f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,13 @@ +#[macro_use] +extern crate apitest; + +use std::collections::HashMap; + +use apitest::api::schema::*; use apitest::api::router::*; use apitest::api::config::*; use apitest::api::server::*; +use apitest::getopts; //use failure::*; use lazy_static::lazy_static; @@ -13,6 +20,13 @@ use hyper; fn main() { println!("Fast Static Type Definitions 1"); + let schema = parameter!{ + name => ApiString!{ optional => false } + }; + + let args: Vec = std::env::args().skip(1).collect(); + getopts::parse_arguments(&args, &schema); + let addr = ([127, 0, 0, 1], 8007).into(); lazy_static!{